Mapa de calor R con paleta de colores divergente

Estoy tratando de crear un mapa de calor simple en R, usando una paleta de colores divergente. Quiero usar un degradado para que todos los números por debajo de un umbral N se designen con un color (por ejemplo, púrpura) y todos los números por encima del umbral se designen con otro color (por ejemplo, naranja). Cuanto más lejos esté el número del umbral, más oscuro debe ser el color.

Aquí hay un conjunto de datos de muestra:

Division,COL1,COL2,COL3,COL4,COL5,COL6,COL7
Division 1,31.9221884012222,75.8181694429368,97.0480443444103,96.295954938978,70.5677134916186,63.0451830103993,93.0396212730557
Division 2,85.7012346852571,29.0621076244861,16.9130333233625,94.6443660184741,19.9103083927184,61.9562198873609,72.3791105207056
Division 3,47.1665125340223,99.4153356179595,8.51091076619923,79.1276383213699,41.915355855599,7.45079894550145,24.6946100145578
Division 4,66.0743870772421,24.6163331903517,78.694460215047,42.04714265652,50.2694897353649,73.0409651994705,87.3745442833751
Division 5,29.6664374880493,35.4036891367286,19.2967326845974,5.48460693098605,32.4517334811389,15.5926876701415,76.0523204226047
Division 6,95.4969164915383,8.63230894319713,61.7535551078618,24.5590241160244,25.5453423131257,56.397921172902,44.4693325087428
Division 7,87.5015622004867,28.7770316936076,56.5095080062747,34.6680747810751,28.1923673115671,65.0204187724739,13.795713102445
Division 8,70.1077231671661,72.4712177179754,38.4903231170028,36.1821102909744,97.0875509083271,17.184783378616,78.2292529474944
Division 9,47.3570406902581,90.2257485780865,65.6037972308695,77.0234781783074,25.6294377148151,84.900529962033,82.5080851092935
Division 10,58.0811711959541,0.493217632174492,58.5604055318981,53.5780876874924,9.12552657537162,20.313960686326,78.1371118500829
Division 11,34.6708688884974,76.711881859228,22.6064443588257,22.1724311355501,5.48891355283558,79.1159523651004,56.8405059166253
Division 12,33.6812808644027,44.1363711375743,70.6362190190703,3.78900407813489,16.6075889021158,9.12654218263924,39.9711143691093

Aquí hay un fragmento simple para producir un mapa de calor a partir de los datos anteriores

data <- read.csv("dataset.csv", sep=",")
row.names(data) <- data$Division
data <- data[,2:7]
data_matrix <- data.matrix(data) 
heatmap(data_matrix, Rowv=NA, Colv=NA, col = heat.colors(256), scale="column", margins=c(5,10))

¿Cómo puedo modificar el código anterior para producir:

  • un degradado de color (naranja) para todos los números POR ENCIMA DE 50 (más oscuro cuanto más lejos esté el número de 50)
  • un degradado de color (púrpura) para todos los números POR DEBAJO de 50 (más oscuro cuanto más lejos esté el número de 50)
  • Es bueno tener (pero opcional) escribir el valor del número en la celda de la cuadrícula
  • Es bueno tener (pero opcional), use un color diferente para la celda de la cuadrícula que es EXACTAMENTE el número de umbral (50 en este caso)

[[Editar]]

acabo de ver esto pregunta sobre SO, que parece ser muy similar. La respuesta usa ggplot (del cual no tengo experiencia), y hasta ahora no he podido adaptar la solución ggplot a mis datos un poco más complicados.

preguntado el 11 de junio de 12 a las 19:06

el RColorBrewer el paquete tiene paletas agradables: intente RColorBrewer:::brewer.pal(11,"PuOr"), luego especifique un argumento de ruptura, aunque es posible que deba hacerlo a través del image() función en su lugar. -

@timriffe: buena sugerencia. Robé su combinación de colores para mi respuesta a continuación, espero que no le importe;) -

@JoshO'Brien seguro. ¡bien hecho interpolando sobre el espacio del laboratorio! -

2 Respuestas

Esto debería llevarte la mayor parte del camino. (Tenga en cuenta que tendrá que configurar scale="none" si desea que los colores representados se correspondan con los valores reales (en lugar de los reescalados) de las celdas).

ncol <- 100

## Make a vector with n colors
cols <- RColorBrewer:::brewer.pal(11,"PuOr")  # OR c("purple","white","orange")  
rampcols <- colorRampPalette(colors = cols, space="Lab")(ncol)
rampcols[(n/2) + 1] <- rgb(t(col2rgb("green")), maxColorValue=256) 

## Make a vector with n+1 breaks
rampbreaks <- seq(0, 100, length.out = ncol+1)

## Try it out
heatmap(data_matrix, Rowv = NA, Colv = NA, scale="none",
        col = rampcols, breaks = rampbreaks)

enter image description here

EDITAR

Para un control más preciso sobre la ubicación del umbral, sugiero crear dos paletas separadas, una para valores inferiores al umbral y otra para valores superiores al umbral, y luego "suturarlas". Pruebe algo como esto, jugando con diferentes valores para Min, Max, Thresh, etc .:

nHalf <- 50

Min <- 0
Max <- 100
Thresh <- 50

## Make vector of colors for values below threshold
rc1 <- colorRampPalette(colors = c("purple", "white"), space="Lab")(nHalf)    
## Make vector of colors for values above threshold
rc2 <- colorRampPalette(colors = c("white", "orange"), space="Lab")(nHalf)
rampcols <- c(rc1, rc2)
## In your example, this line sets the color for values between 49 and 51. 
rampcols[c(nHalf, nHalf+1)] <- rgb(t(col2rgb("green")), maxColorValue=256) 

rb1 <- seq(Min, Thresh, length.out=nHalf+1)
rb2 <- seq(Thresh, Max, length.out=nHalf+1)[-1]
rampbreaks <- c(rb1, rb2)

heatmap(data_matrix, Rowv = NA, Colv = NA, scale="none",
        col = rampcols, breaks = rampbreaks)

Respondido el 11 de junio de 12 a las 23:06

¡Gracias Jos!. ¡No puedo creer que hayas logrado crear esto con tan pocas líneas de código!. Soy bastante nuevo en todo esto (R, RColorBrewer, etc.), y me cuesta entender su uso de 'números mágicos' (por ejemplo, 100, 11 etc.), y cómo se relaciona con mis datos originales y el 'valor de umbral de corte de 50 (como se usa en mi ejemplo). ¿Podría arrojar algo de luz sobre: 1. ¿De dónde vienen los números que usas? 2. ¿Cómo puedo establecer un número de umbral?. 3. No está claro cómo (o dónde) está configurando los criterios de fondo verde si el valor de la celda es aproximado = umbral. - Homúnculo reticulli

@JoshOBrien: por último, pero no menos importante, si quisiera escribir los valores en la celda (como en este ejemplo: stackoverflow.com/questions/8161014/custom-heat-map-in-r/…), ¿cómo puedo hacer eso?. Gracias - Homúnculo reticulli

@JoshOBrien: La razón por la que preguntaba cómo configurar el umbral es para poder, por ejemplo, usar diferentes colores para números positivos y negativos (estableciendo el umbral en 0). No puedo averiguar cómo hacer esto a partir del fragmento... - Homúnculo reticulli

@HomunculusReticulli: hay demasiado para mí como para querer explicarlo allí. Debería poder aprender cómo funciona el código jugando con él y haciendo muchas ?xxx sin que importe xxx = someFunctionMysteriousToMe. Como para RColorBrewer, es una interfaz R para las paletas desarrolladas por este proyecto. Prueba esto para aprender un poco más: library(RColorBrewer); display.brewer.all(); display.brewer.pal(n=3, "PuOr"); display.brewer.pal(n=7, "PuOr"), etc... ¡Mucha suerte! (Tenga en cuenta que edité mi respuesta para dar un ejemplo de cómo especificar el valor de umbral de manera más flexible). - Josh O'Brien

Encontré este hilo muy útil y también saqué algunas ideas de aquí, pero para mis propósitos necesitaba generalizar algunas cosas y quería usar el paquete RColorBrewer. Mientras trabajaba en él, el Dr. Brewer (del famoso Color Brewer) se detuvo en mi oficina y me dijo que necesitaba interpolar dentro de los cortes de color más pequeños en lugar de solo elegir los puntos finales. Pensé que a otros les podría resultar útil, así que estoy publicando mi función aquí para la posteridad.

La función toma su vector de datos, el nombre de una paleta divergente de colorBrewer y el punto central de su combinación de colores (el valor predeterminado es 0). Muestra una lista que contiene 2 objetos: un objeto classIntervals y un vector de colores: la función está configurada para interpolar un total de 100 colores, pero eso se puede modificar con cuidado.

diverge.color <- function(data,pal_choice="RdGy",centeredOn=0){
  nHalf=50
  Min <- min(data,na.rm=TRUE)
  Max <- max(data,na.rm=TRUE)
  Thresh <- centeredOn
  pal<-brewer.pal(n=11,pal_choice)
  rc1<-colorRampPalette(colors=c(pal[1],pal[2]),space="Lab")(10)
  for(i in 2:10){
    tmp<-colorRampPalette(colors=c(pal[i],pal[i+1]),space="Lab")(10)
    rc1<-c(rc1,tmp)
  }
  rb1 <- seq(Min, Thresh, length.out=nHalf+1)
  rb2 <- seq(Thresh, Max, length.out=nHalf+1)[-1]
  rampbreaks <- c(rb1, rb2)
  cuts <- classIntervals(data, style="fixed",fixedBreaks=rampbreaks)
  return(list(cuts,rc1))
}

en mi trabajo, estoy usando este esquema para trazar una capa ráster (rs) usando spplot así:

brks<-diverge.color(values(rs))
spplot(rs,col.regions=brks[[2]],at=brks[[1]]$brks,colorkey=TRUE))

Respondido 14 Feb 14, 16:02

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.