Mostrando entradas con la etiqueta length. Mostrar todas las entradas
Mostrando entradas con la etiqueta length. Mostrar todas las entradas

2019-01-02

Representar shapefiles (SHP) con ggplot2

Problema

Deseamos representar shapefiles (SHP) con ggplot2. Obtendremos los datos de las regiones administratitvas siguiendo los pasos de esta entrada.

Solución

Voy a representar los municipios de España. Generaré unos datos aleatorios para cada uno de ellos y asignarles luego una escala continua. Creo dos gráficos separados para península y Baleares, y Canarias para ganar en claridad. Finalmente represento Castilla-La Mancha, y dejo un enlace a un pdf para poder hacer zoom en el resto de la península y Baleares y apreciar el detalle.

library(tidyverse)
library(raster)
shp <- getData("GADM", country = "ES", level = 4)
shp.pen <- shp[shp@data$NAME_1 != "Islas Canarias", ]
shp.can <- shp[shp@data$NAME_1 == "Islas Canarias", ]

# Convertimos shapefiles a data frames
df.spain <- fortify(shp, region = "NAME_4")
df.pen <- fortify(shp.pen, region = "NAME_4")
df.can <- fortify(shp.can, region = "NAME_4")

# Datos aleatorios
set.seed(2015)
random.df <- data.frame(id = unique(df.spain[, 'id']),
                        random = runif(
                          n = length(unique(df.spain[, 'id'])),
                          min = 25,
                          max = 75
                        ))
df.pen <-
  merge(df.pen, random.df, by = 'id', all.x = TRUE)
df.can <-
  merge(df.can, random.df, by = 'id', all.x = TRUE)

# Gráficos con ggplot2
# Península y Baleares
p.pen <-
  ggplot(df.pen, aes(x = long, y = lat, group = group)) +
  geom_polygon(aes(fill = random), colour = "white", size = 0.1) +
  labs(x = " ", y = " ") +
  theme_bw() +
  scale_fill_viridis_c('Datos aleatorios', option = "magma", direction = -1) +
  coord_map() +
  theme(
    panel.grid.minor = element_blank(),
    panel.grid.major = element_blank(),
    panel.border = element_blank(),
    axis.ticks = element_blank(),
    axis.text.x = element_blank(),
    axis.text.y = element_blank(),
    legend.position = "bottom"
  )

# Canarias
p.can <-
  ggplot(df.can, aes(x = long, y = lat, group = group)) +
  geom_polygon(aes(fill = random), colour = "white", size = 0.1) +
  labs(x = " ", y = " ") +
  theme_bw() +
  scale_fill_viridis_c('Datos aleatorios', option = "magma", direction = -1) +
  coord_map() +
  theme(
    panel.grid.minor = element_blank(),
    panel.grid.major = element_blank(),
    panel.border = element_blank(),
    axis.ticks = element_blank(),
    axis.text.x = element_blank(),
    axis.text.y = element_blank(),
    legend.position = "bottom"
  )


# Mostramos los gráficos
p.pen
p.can

Mapas

Enlace al pdf.

  • Península y Baleares
  • Canarias
  • Castilla-La Mancha
  • Entradas relacionadas

    Referencias

    2018-01-20

    Rellenar área con teselas en ggplot2

    Problema

    Con ggplot2 queremos rellenar una región cuadrada con teselas cuadradas. El intento original del usuario que plantéo la pregunta fue:

    • Datos
    set.seed(1)
    library(ggplot2)
    # Datos
    l = 1000
    a = seq(0, 1, 1 / (l - 1))
    x = rep(a, each = length(a))
    y = rep(a, length(a))
    k = length(x)
    c = sample(1:10, k, replace = TRUE)
    data <- data.frame(x, y, c)
    # Gráfico
    ggplot(data, aes(x = x, y = y)) + geom_point(shape = 15, color = c)
    

    Solución

    • Alternativa 1
    • Reducimos el tamaño del data frame, l = 10 en el código anterior para poder apreciar los cuadrados. Y usamos el argumento "white" como colour p para resaltar las teselas con un contorno blanco.

      ggplot(data, aes(x = x, y = y, fill = c)) + geom_tile(colour = "white")
      
    • Alternativa 2
    • Creamos manualmente una paleta, y empleamos coord_equal para generar cuadrados, forzando a que una unidad en el eje x tenga la misma longitud que una unidad en el eje y.

      colors<-c("peachpuff", "yellow", "orange", "orangered", "red", 
                "darkred","firebrick", "royalblue", "darkslategrey", "black")
      ggplot(data, aes(x = x, y = y)) +
        geom_tile(aes(fill = factor(c)), colour = "white") +
        scale_fill_manual(values = colors, name = "Colours") +
        coord_equal()
      

    Notas

    Para apreciar lo que sucede cuando creamos el gráfico original con geom_point, reducimos el tamaño del data frame, a 10 x 10. Lo representamos seguido de las dos alternativas propuestas.

    • Nuevo data frame
    • l = 100
      a = seq(0, 1, 1 / (l - 1))
      x = rep(a, each = length(a))
      y = rep(a, length(a))
      k = length(x)
      c = sample(1:10, k, replace = TRUE)
      data <- data.frame(x, y, c)
      
    • Gráfico original
    • ggplot(data, aes(x = x, y = y)) + geom_point(shape = 15, color = c)
      
    • Alternativa 1
    • ggplot(data, aes(x = x, y = y, fill = c)) + geom_tile(colour = "white")
      
    • Alternativa 2
    • colors<-c("peachpuff", "yellow", "orange", "orangered", "red", 
                "darkred","firebrick", "royalblue", "darkslategrey", "black")
      ggplot(data, aes(x = x, y = y)) +
        geom_tile(aes(fill = factor(c)), colour = "white") +
        scale_fill_manual(values = colors, name = "Colours") +
        coord_equal()
      

    Referencias

    2016-01-28

    Ordenar un data frame por la frecuencia de una columna en R

    Title

    Problema

    Tenemos el siguiente data frame. Y, sin agrupar, queremos ordenarlo de mayor a menor por la frecuencia de la columna Salary. Es decir, 1002 se repite tres veces en nuestro data frame, 1001 y 3001 dos veces y resto una vez.

       Region  ID Salary
    1       1  A1    100
    2       1  A2   1001
    3       1  A3   2000
    4       1  A4   2431
    5       1  A5   1001
    6       2  A6   1002
    7       2  A7   1002
    8       2  A8   1002
    9       3  A9   3001
    10      3 A10   3001
    11      3 A11   4001
    
    df <- structure(list(Region = c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 
    3L, 3L), ID = c("A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", 
    "A9", "A10", "A11"), Salary = c(100L, 1001L, 2000L, 2431L, 1001L, 
    1002L, 1002L, 1002L, 3001L, 3001L, 4001L)), .Names = c("Region", 
    "ID", "Salary"), class = "data.frame", row.names = c(NA, -11L
    ))
    

    Solución

    • Paquete base
    • Con transform creamos la columna frecuencia (freq) y después con order, ordenamos por ella. Por defecto es en orden ascendente al preceder la columna del signo menos, indicamos que sea en orden descendente.

      df <- transform(df, freq = ave(seq(nrow(df)), Salary, FUN = length))
      df[order(-df$freq), ]
      
         Region  ID Salary freq
      6       2  A6   1002    3
      7       2  A7   1002    3
      8       2  A8   1002    3
      2       1  A2   1001    2
      5       1  A5   1001    2
      9       3  A9   3001    2
      10      3 A10   3001    2
      1       1  A1    100    1
      3       1  A3   2000    1
      4       1  A4   2431    1
      11      3 A11   4001    1
      
    • dplyr
    • library(dplyr)
      df %>%
        add_count(Salary) %>% 
        arrange(-n)
      
         Region  ID Salary n
      1       2  A6   1002 3
      2       2  A7   1002 3
      3       2  A8   1002 3
      4       1  A2   1001 2
      5       1  A5   1001 2
      6       3  A9   3001 2
      7       3 A10   3001 2
      8       1  A1    100 1
      9       1  A3   2000 1
      10      1  A4   2431 1
      11      3 A11   4001 1
      

    Referencias

    Nube de datos