Come produrre una mappa di calore con ggplot2?
Domanda
Sto cercando di produrre una mappa di calore utilizzando ggplot2. Ho trovato questo esempio , che essenzialmente sto provando replicare con i miei dati, ma ho difficoltà. I miei dati sono un semplice file .csv simile a questo:
people,apple,orange,peach
mike,1,0,6
sue,0,0,1
bill,3,3,1
ted,1,1,0
Vorrei produrre una semplice mappa di calore in cui il nome del frutto è sull'asse xe la persona è sull'asse y. Il grafico dovrebbe rappresentare quadrati in cui il colore di ogni quadrato è una rappresentazione del numero di frutta consumata. Il quadrato corrispondente a mike:peach
dovrebbe essere il più scuro.
Ecco il codice che sto usando per provare a produrre la mappa di calore:
data <- read.csv("/Users/bunsen/Desktop/fruit.txt", head=TRUE, sep=",")
fruit <- c(apple,orange,peach)
people <- data[,1]
(p <- ggplot(data, aes(fruit, people)) + geom_tile(aes(fill = rescale), colour = "white") + scale_fill_gradient(low = "white", high = "steelblue"))
Quando tracciamo questi dati ottengo il numero di frutti sull'asse x e le persone sull'asse y. Inoltre non ottengo sfumature di colore che rappresentano il numero di frutti. Come posso ottenere i nomi dei frutti sull'asse x con il numero di frutti mangiati da una persona visualizzato come mappa di calore? L'output corrente che ricevo in R è simile a questo:
Soluzione
Essere onesto @ Dr.Bunsen - Il tuo esempio sopra è stato scarsamente riproducibile e non hai letto la prima parte del tutorial che collegato .Ecco probabilmente quello che stai cercando:
library(reshape)
library(ggplot2)
library(scales)
data <- structure(list(people = structure(c(2L, 3L, 1L, 4L),
.Label = c("bill", "mike", "sue", "ted"),
class = "factor"),
apple = c(1L, 0L, 3L, 1L),
orange = c(0L, 0L, 3L, 1L),
peach = c(6L, 1L, 1L, 0L)),
.Names = c("people", "apple", "orange", "peach"),
class = "data.frame",
row.names = c(NA, -4L))
data.m <- melt(data)
data.m <- ddply(data.m, .(variable), transform, rescale = rescale(value))
p <- ggplot(data.m, aes(variable, people)) +
geom_tile(aes(fill = rescale), colour = "white")
p + scale_fill_gradient(low = "white", high = "steelblue")
.
Altri suggerimenti
Sette (!) anni dopo, il modo migliore per formattare correttamente i dati è utilizzare tidyr
anziché reshape
Utilizzando gather
da tidyr
, è molto facile riformattare i dati per ottenere le 3 colonne previste (person
per l'asse y, fruit
per l'asse x e count
per i valori):
library("dplyr")
library("tidyr")
hm <- readr::read_csv("people,apple,orange,peach
mike,1,0,6
sue,0,0,1
bill,3,3,1
ted,1,1,0")
hm <- hm %>%
gather(fruit, count, apple:peach)
#syntax: key column (to create), value column (to create), columns to gather (will become (key, value) pairs)
I dati ora hanno questo aspetto:
# A tibble: 12 x 3
people fruit count
<chr> <chr> <dbl>
1 mike apple 1
2 sue apple 0
3 bill apple 3
4 ted apple 1
5 mike orange 0
6 sue orange 0
7 bill orange 3
8 ted orange 1
9 mike peach 6
10 sue peach 1
11 bill peach 1
12 ted peach 0
Perfetto! Cominciamo a tracciare. Il geom di base per fare una heatmap con ggplot2 è geom_tile
a cui forniremo x
estetico, y
e fill
.
library("ggplot2")
ggplot(hm, aes(x=x, y=y, fill=value)) + geom_tile()
OK, non male, ma possiamo fare molto meglio.
- Per le mappe di calore, mi piace il
theme_bw()
del tema in bianco e nero che elimina lo sfondo grigio. -
Mi piace anche usare una tavolozza da
RColorBrewer
(condirection = 1
per ottenere i colori più scuri per valori più alti, o -1 altrimenti). Ci sono molte tavolozze disponibili: Reds, Blues, Spectral, RdYlBu (red-yellow-blue), RdBu (red-blue), ecc. Di seguito uso "Greens". EseguiRColorBrewer::display.brewer.all()
per vedere come appaiono le tavolozze. -
Se vuoi che le tessere siano quadrate, usa semplicemente
coord_equal()
. -
Trovo spesso che la legenda non sia utile, ma dipende dal tuo caso d'uso particolare. Puoi nascondere la legenda
fill
conguides(fill=F)
. -
Puoi stampare i valori sopra i riquadri utilizzando
geom_text
(ogeom_label
). Ci vuole l'esteticax
,y
elabel
ma nel nostro caso vengono ereditatix
ey
. Puoi anche stampare valori più alti più grandi passandosize=count
come estetica: in tal caso dovrai anche passaresize=F
aguides
per nascondere la legenda delle dimensioni. -
Puoi tracciare linee attorno alle tessere passando un
color
ageom_tile
.
Mettendo tutto insieme:
ggplot(hm, aes(x=fruit, y=people, fill=count)) +
# tile with black contour
geom_tile(color="black") +
# B&W theme, no grey background
theme_bw() +
# square tiles
coord_equal() +
# Green color theme for `fill`
scale_fill_distiller(palette="Greens", direction=1) +
# printing values in black
geom_text(aes(label=count), color="black") +
# removing legend for `fill` since we're already printing values
guides(fill=F) +
# since there is no legend, adding a title
labs(title = "Count of fruits per person")
Per rimuovere qualsiasi cosa, rimuovi semplicemente la riga corrispondente.