Gibt es in R eine Möglichkeit, eine Legende mit zwei Achsen zu zeichnen?

8

Ich möchte eine Legende mit zwei Achsen zeichnen. Insbesondere habe ich zwei klassifizierte räumliche Objekte kombiniert, wobei das erste die Intensität eines Ereignisses und das zweite die Wahrscheinlichkeit des Ereignisses an diesem Ort zeigt. Ich möchte eine Legende erstellen, die zeigt, wo die Pixel des kombinierten Rasters in jede Kategorie fallen. Die Legende, die ich erstellen möchte, sieht ungefähr so ​​aus: Legende mit zwei Achsen .

Geben Sie hier die Bildbeschreibung ein

Die normale Legende der klassifizierten Daten sieht folgendermaßen aus: Originallegende

Geben Sie hier die Bildbeschreibung ein

Hier ist ein reproduzierbares Beispiel für die Art der Daten, die ich verwende:

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"))

Zeichnen Sie die Ausgabe von oben

Geben Sie hier die Bildbeschreibung ein

Der einfachste Weg wäre, den Plot zu erstellen und die Legende später in einem Grafikeditor hinzuzufügen ... aber ich bin sicher, dass es einen Weg geben muss, dies in R selbst zu tun! Ich plane derzeit mit dem rasterVis-Paket, aber wenn es Antworten in ggplot oder base R gibt, sind diese gleichermaßen willkommen.

Wenn es sinnvoller wäre, ein reproduzierbares Beispiel für die Zwischenschritte (dh mit den Intensitäts- / Wahrscheinlichkeitsrastern) zu haben, lassen Sie es mich wissen und ich kann diese erstellen.

dee_2_dee
quelle
1
Das nächste , was ich auf Github gesehen habe, ist github.com/clauswilke/multiscales , aber es ist nicht genau Ihr Beispiel.
Teunbrand
1
Mit habe rasterVisich dieses Bild produziert . Wenn Sie danach suchen, probieren Sie den hier verfügbaren Code aus (Abschnitt "Bivariate Legende).
Oscar Perpiñán
@ OscarPerpiñán Ich glaube, Ihr Beispiel kommt dem, was ich mir erhoffe, am nächsten (in der Lage, die Legende oben auf der Karte zu zeichnen). Ich habe Schwierigkeiten, einen Teil Ihres Codes zu verstehen. Was ist der Zweck des pList-Schritts? Ist dies erforderlich, damit nachfolgende Schritte ordnungsgemäß funktionieren, oder ist es spezifisch für die von Ihnen erstellte Karte?
dee_2_dee
1
@ dee_2_dee In diesem Schritt wird eine Liste von Level-Plots erstellt, die jeweils einer Klasse entsprechen (siehe Code oben im Abschnitt "Kategoriale Daten"). Diese Liste wird zu einem globalen Plot mit Reduceund reduziert +.trellis.
Oscar Perpiñán

Antworten:

4

Eine Lösung besteht darin, zwei Diagramme zu erstellen und diese beispielsweise mithilfe der grid.arrangeFunktion aus dem gridExtraPaket zu kombinieren

Zuerst konvertiere ich Ihren rasterLayer mithilfe der in diesem Beitrag veröffentlichten Funktion in einen Tibble: Überlagern Sie den Raster-Layer auf der Karte in ggplot2 in R?

(PS: Ich habe Ihr valObjekt so geändert, dass nur 16 verschiedene Farben zu dem von Ihnen angegebenen Farbmuster passen. In Ihrem Beispiel valhat es 20 verschiedene Werte.)

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)

Dann erstelle ich das Faustdiagramm, die Heatmap mit 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())

Dann erstelle ich einen separaten Datenrahmen für die Legende:

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    

Jetzt habe ich die Handlung für die Legende gemacht:

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))

Und schließlich kombiniere ich sie:

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

Geben Sie hier die Bildbeschreibung ein

Sieht es so aus, wie Sie es bekommen wollen?


NB: Sie können Ihr Rasterobjekt wahrscheinlich direkt zeichnen, ggplot2aber ich war mir nicht sicher, wie genau es ablaufen soll. Sie können auch mit dem Layout von spielen grid.arrange, damit die Handlung genau so aussieht, wie Sie es möchten

dc37
quelle