¿Hay alguna forma en R de trazar una leyenda con dos ejes?

8

Me gustaría trazar una leyenda con dos ejes. Específicamente, he combinado dos objetos espaciales que se han clasificado, el primero que muestra la intensidad de un evento y el segundo que muestra la probabilidad del evento en esa ubicación. Quiero crear una leyenda que muestre dónde caen los píxeles del ráster combinado en cada categoría. La leyenda que me gustaría crear se vería así: Leyenda con dos ejes .

ingrese la descripción de la imagen aquí

La leyenda normal de los datos clasificados se ve así: Leyenda original

ingrese la descripción de la imagen aquí

Aquí hay un ejemplo reproducible del tipo de datos que estoy usando:

library(raster)
library(rasterVis)

# setseed
set.seed(999)

# create raster (example of what would be the outcome of combining intensity and probability rasters)
plot.me<- raster(xmn=-110, xmx=-90, ymn=40, ymx=60, ncols=40, nrows=40)
val <- c(100:104, 200:204, 300:304, 400:404)
plot.me<- setValues(plot.me, sample(val,ncell(plot.me),replace=T))


######  Plotting

plot.me <- ratify(plot.me)
levelplot(plot.me,att="ID" ,
          col.regions=c("#beffff","#73dfff","#d0ff73","#55ff00",
                        "#73b2ff","#0070ff","#70a800","#267300",
                        "#f5f57a","#ffff00","#e8beff","#df73ff",
                        "#f5ca7a","#ffaa00","#e600a9","#a80084"))

Trazar salida desde arriba

ingrese la descripción de la imagen aquí

La forma más fácil sería crear la trama y agregar la leyenda más adelante en un editor de gráficos ... ¡pero estoy seguro de que debe haber una manera de hacerlo en R! Actualmente estoy tramando con el paquete rasterVis, pero si hay respuestas en ggplot o base R, estas son igualmente bienvenidas.

Si fuera más útil tener un ejemplo reproducible de los pasos intermedios (es decir, con los rásteres de intensidad / probabilidad), hágamelo saber y puedo producirlos.

dee_2_dee
fuente
1
Lo más cercano que he visto viviendo en github es github.com/clauswilke/multiscales , pero no es exactamente su ejemplo.
teunbrand
1
Usando rasterVisproduje esta imagen . Si esto es lo que está buscando, pruebe el código disponible aquí (sección "Leyenda bivariada).
Oscar Perpiñán
@ OscarPerpiñán Siento que tu ejemplo es el más cercano a lo que esperaba (capaz de trazar la leyenda en la parte superior del mapa). Tengo dificultades para comprender una parte de su código: ¿cuál es el propósito del paso pList? ¿Es eso necesario para que los pasos posteriores funcionen correctamente o es específico para el mapa que estaba creando?
dee_2_dee
1
@ dee_2_dee Este paso genera una lista de diagramas de niveles, cada uno de ellos correspondiente a una clase (consulte el código anterior, en la sección "Datos categóricos"). Esta lista se contrae en un diagrama global con Reducey +.trellis.
Oscar Perpiñán

Respuestas:

4

Una solución será hacer dos gráficos y combinarlos usando la grid.arrangefunción del gridExtrapaquete, por ejemplo

Primero, convierto su rasterLayer en un tibble usando la función publicada en esta publicación: ¿ Superponer capa de ráster en el mapa en ggplot2 en R?

(PD: modifiqué su valobjeto para hacer que solo 16 colores diferentes coincidan con el patrón de color que proporcionó. En su ejemplo, valtiene 20 valores diferentes)

val <- c(101:104, 201:204, 301:304, 401:404) # correction from OP's question to match 16 different values

library(raster)
gplot_data <- function(x, maxpixels = 50000)  {
  x <- raster::sampleRegular(x, maxpixels, asRaster = TRUE)
  coords <- raster::xyFromCell(x, seq_len(raster::ncell(x)))
  ## Extract values
  dat <- utils::stack(as.data.frame(raster::getValues(x))) 
  names(dat) <- c('value', 'variable')

  dat <- dplyr::as.tbl(data.frame(coords, dat))

  if (!is.null(levels(x))) {
    dat <- dplyr::left_join(dat, levels(x)[[1]], 
                            by = c("value" = "ID"))
  }
  dat
}

df <- gplot_data(plot.me)

Luego, creo el diagrama de puño, el mapa de calor usando geom_tile:

library(ggplot2)
plot <- ggplot(df, aes(x = x, y = y, fill = as.factor(value)))+
  geom_tile(show.legend = FALSE)+
  coord_fixed(ratio = 20/20)+
  scale_fill_manual(values = c("#beffff","#73dfff","#d0ff73","#55ff00",
                               "#73b2ff","#0070ff","#70a800","#267300",
                               "#f5f57a","#ffff00","#e8beff","#df73ff",
                               "#f5ca7a","#ffaa00","#e600a9","#a80084"))+
  scale_y_continuous(name = "Latitude",labels = paste(c(40,45,50,55,60),"°N"))+
  scale_x_continuous(name = "Longitude",labels = paste(c(-110,-105,-100,-95,-90),"°W"))+
  theme_linedraw()+
  theme(panel.border = element_rect(size = 2),
        axis.text = element_text(size = 10),
        axis.title = element_text(size = 10),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank())

Luego, creo un marco de datos separado para la leyenda:

library(tidyverse)
df_legend <- data.frame(value = unique(df$value))
df_legend <- df_legend %>% rowwise() %>% 
  mutate(Dim1 = unlist(strsplit(as.character(value),""))[1],
         Dim3 = unlist(strsplit(as.character(value),""))[3])

Source: local data frame [16 x 3]
Groups: <by row>

# A tibble: 16 x 3
   value Dim1  Dim3 
   <int> <chr> <chr>
 1   404 4     4    
 2   204 2     4    
 3   304 3     4    
 4   104 1     4    
 5   202 2     2    
 6   302 3     2    
 7   203 2     3    
 8   301 3     1    
 9   402 4     2    
10   401 4     1    
11   303 3     3    
12   102 1     2    
13   201 2     1    
14   103 1     3    
15   403 4     3    
16   101 1     1    

Ahora, hice la trama de la leyenda:

legend <- ggplot(df_legend, aes(x = as.factor(Dim1), y = as.factor(Dim3), fill = as.factor(value)))+
  geom_tile(show.legend = FALSE, color = "black")+
  coord_fixed(ratio = 1)+
  scale_fill_manual(values = c("#beffff","#73dfff","#d0ff73","#55ff00",
                               "#73b2ff","#0070ff","#70a800","#267300",
                               "#f5f57a","#ffff00","#e8beff","#df73ff",
                               "#f5ca7a","#ffaa00","#e600a9","#a80084"))+
  theme_linedraw()+
  labs(x = "Dim1", y = "Dim3")+
  theme(panel.border = element_rect(size = 2),
        axis.text = element_text(size = 10),
        axis.title = element_text(size = 10))

Y finalmente, los combino:

library(gridExtra)
grid.arrange(plot, legend, layout_matrix = rbind(c(1,1,2),c(1,1,3)))

ingrese la descripción de la imagen aquí

¿Se ve lo que estás tratando de conseguir?


NB: Probablemente pueda trazar directamente su objeto ráster, ggplot2pero no estaba seguro del procedimiento exacto. Además, puedes jugar con el diseño grid.arrangepara hacer que la trama se vea exactamente como quieres

dc37
fuente