3 votos

Trazado de un terra raster categórico con un mapa de colores

Estoy tratando de trazar una categoría terra con un color explícito para cada nivel, como se haría con un ráster de cobertura del suelo, pero con problemas cuando el ráster no tiene todos los niveles del factor.

Primero cree un ráster con valores numéricos de 1 a 10, hágalo categórico, y trace:

r2 = rast(matrix(1:10,2,5))
r2 = as.factor(r2)
levels(r2) = data.frame(value=1:10, desc=paste0("L",1:10))
plot(r2)

enter image description here

Genial, ahora quiero trazar con cada nivel impar coloreado de rojo y cada nivel par coloreado de azul, así que hago una paleta de longitud 10:

rb = rep(c("red","blue"),5)
plot(r2, col=rb)

enter image description here

Genial, pero supongamos que mi trama no tiene todos los niveles. Por ejemplo, hagamos una copia del raster y pongamos la primera celda en un nivel 2:

r2c = r2
r2c[1] = 2
plot(r2c, col=rb)

enter image description here

Y ahora los colores se han invertido y ya no se alterna con los niveles de 10 factores. El nivel 10 (azul) no es del mismo color que el nivel 8 (rojo).

Creo que lo que ocurre es que el color especifica colores para todos los valores que existe en la trama, no todos los valores que existen en los niveles. Así que si suelto el primer elemento de la paleta (porque ya no hay nivel 1 en la trama) obtengo esto:

plot(r2c, col=rb[-1])

enter image description here

que es lo que busco. Pero esto es un problema, porque significa que cada vez que tengo un mapa de color que contiene valores que no están en la trama (porque tal vez es un recorte de un conjunto más grande), tengo que subconjuntar la paleta de colores de acuerdo con los valores que todavía están presentes en la trama recortada. No encuentro una forma sencilla de decir que "L10" es "azul", y "L3" es "amarillo" y así sucesivamente. ¿O me lo he perdido?

Edición: la solución podría estar en coltab pero creo que eso requiere hacer una paleta de colores completa de 255 filas. Se puede hacer, pero no está bien.

2voto

SteveBurkett Puntos 960

coltab no es tan doloroso como puede parecer (los docs están un poco detrás de los hechos). Puede hacer

r2 = rast(matrix(1:10,2,5))
r2 = as.factor(r2)
levels(r2) = data.frame(value=1:10, desc=paste0("L",1:10))
# first color-table value is zero, so starting with "blue"
coltab(r2) = rep(c("blue", "red"), 6)
plot(r2)

Y los colores ahora son los mismos

r2c = r2
r2c[1] = 2
plot(r2c)

No obstante, su argumento sigue siendo válido. Sería útil tener combinaciones estables de color/clase vinculando los colores a los niveles conocidos, estén o no presentes. Ahora he implementado eso en la versión 1.5-50 de terra.

Con esa versión, también se puede establecer una tabla de colores por ID

library(terra)
r <- rast(ncols=3, nrows=2, vals=c(10:12, 23:25))
coltab(r) <- data.frame(values=c(10:12, 23:25), cols=rainbow(6))
plot(r)

Y creo que debería convertirse en el enfoque canónico, ya que es la forma más clara y flexible de hacerlo.

0voto

hogliux Puntos 8

Ver una solución usando ggplot y tidyterra. Es posible que tenga que utilizar drop = FALSE en el scale_fill_* llamar:

library(terra)
#> terra 1.5.21
library(tidyterra)
#> ── Attaching packages ────────────────────────────────── tidyterra 0.1.0.9002 ──
#> 
#> Suppress this startup message by setting Sys.setenv(tidyterra.quiet = TRUE)
#> ✔ tibble 3.1.7     ✔ dplyr  1.0.9
#> ✔ tidyr  1.2.0
r2 = rast(matrix(1:10,2,5))
r2 = as.factor(r2)
levels(r2) = data.frame(value=1:10, desc=paste0("L",1:10))

library(ggplot2)
#> 
#> Attaching package: 'ggplot2'
#> The following object is masked from 'package:terra':
#> 
#>     arrow
rb = rep(c("red","blue"),5)

ggplot() +
  geom_spatraster(data=r2) +
  scale_fill_manual(values = rb)

r2c = r2
r2c[1] = 2

ggplot() +
  geom_spatraster(data=r2c) +
  scale_fill_manual(values = rb, drop = FALSE)

Creado el 2022-07-02 por el paquete reprex (v2.0.1)

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X