2015-10-09 20 views
5

ho dati contenenti dati numerici a coppie per 10 campioni:Usa facet_grid per il valore a due a due (heatmap) visualizzazione in ggplot2

data = dget(url("https://git.io/vCTpG")) 

I dati si presenta così:

sampleB sampleA ol labelA labelB facetA facetB 
2409  2409  100 2409|B 2409|B B  B 
2409  2413  0 2413|A 2409|B A  B 
2409  2414  0 2414|A 2409|B A  B 
2409  2417  0 2417|C 2409|B C  B 
2409  2411  0 2411|A 2409|B A  B 
2409  2418  0 2418|B 2409|B B  B 
2409  2416  0 2416|C 2409|B C  B 
2409  2412  4 2412|B 2409|B B  B 
2409  2415  0 2415|C 2409|B C  B 
2409  2410  19 2410|A 2409|B A  B 
...  ...  ... ...  ...  ...  ... 

voglio visualizzare la ol valori in una mappa di calore:

library(ggplot2) 
ggplot(data = data, mapping = aes(x=labelA, y=labelB)) + 
    geom_tile(mapping = aes(fill=ol)) + 
    scale_fill_gradient(low = "white", high = "black") + 
    theme(legend.position = "none") + 
    theme(axis.text.x = element_text(angle = 90, hjust = 1)) 

plot without facet

Ora mi piacerebbe strutturare la mappa di calore 10 per 10 per una categoria associata a ciascun campione, ovvero A,B o C in questo esempio. Tuttavia, se uso facet_grid ...

last_plot() + facet_grid(facetA~facetB) 

plot with facet

... questo si traduce in un 30 da 30 piuttosto che in una mappa 10 da 10 di calore che si suddivide in 3 categorie (che mostra ancora solo 100 valori però). Ricordo di aver risolto questo problema utilizzando

last_plot() + facet_grid(facetA~facetB, scales = "free", space = "free") 

in passato, tuttavia, non riesco più a riprodurlo. La soluzione desiderata sarebbe simile a questa (questo è stato rivestiti, non ggplot generata):

enter image description here

Vale a dire un riordinato, raggruppato 10 per 10 matrice.

+1

Potrebbe elaborare ciò che si Ti aspetti di vedere? Sembra abbastanza corretto: la tua immagine totale è una somma di tutte le immagini sfaccettate. Cosa ti aspetti di vedere ad es. per '2409 | B' su una faccetta A vs facet C? Naturalmente, è vuoto. – tonytonov

+0

@tonytonov Ho aggiunto un'immagine creata manualmente per spiegare meglio il risultato desiderato – barbaz

+1

interessante .. cambiando l'ordine delle faccette ti avvicini 'last_plot() + facet_grid (facetB ~ facetA, scale =" free ")' – user20650

risposta

2

È necessario utilizzare facet_wrap() anziché facet_grid() o modificare l'ordine delle faccette in facet_grid() come suggerito nei commenti.

Il motivo è che, per definizione, facet_grid non consente che i limiti degli assi y siano diversi tra i pannelli nella stessa riga. In altre parole, tutti e tre i pannelli nella riga superiore devono avere gli stessi limiti y, tutti e tre i riquadri nella seconda riga devono avere gli stessi limiti y ecc. L'aggiunta di scales = "free_y" significa che la prima riga può avere diversi limiti y dal seconda riga (ma all'interno di una determinata riga, tutti i pannelli devono sempre avere gli stessi limiti y). Nel tuo esempio, quando si utilizza

facet_grid(facetA ~ facetB, scales = "free") 

si stanno costringendo ggplot di utilizzare tutti i valori y per tutte le righe; ad esempio il pannello di sinistra nella riga superiore deve contenere il valore 2418|B poiché tale valore è presente nel pannello centrale della riga superiore. Invertendo l'ordine delle faccette accade di fare il lavoro in questo caso a causa della struttura dei dati. (Sto solo dando un esempio per l'asse y, ma lo stesso vale per i limiti dell'asse x quando si utilizza scales = "free_x".)

Se si desidera avere scale xey differenti per ogni pannello, indipendentemente da quelli accanto ad esso, sarà necessario utilizzare facet_wrap.

Modifica Una spiegazione più dettagliata di come ottenere la figura desiderata.Tornando al tuo esempio specifico, invertendo le vostre sfaccettature daranno

p <- ggplot(data = data, mapping = aes(x=labelA, y=labelB)) + 
    geom_tile(mapping = aes(fill=ol)) + 
    scale_fill_gradient(low = "white", high = "black") + 
    theme(legend.position = "none") + 
    theme(axis.text.x = element_text(angle = 90, hjust = 1)) + 
    facet_grid(facetB ~ facetA, scales = "free") 
p 

enter image description here

Questo contiene tutti i pannelli che si desidera. Per ottenere l'ordine che stai chiedendo è semplicemente una questione di riorganizzare le righe. Questo può essere fatto impostando l'ordine dei livelli di facetB (modificare: o, come @ user20650 suggerito nei commenti, impostando as.table=FALSEin facet_grid()):

data1 <- data  
data1$facetB <- factor(data1$facetB, levels = c("C", "B", "A")) 
p %+% data1 

enter image description here

+0

Non è quello che voglio, voglio la figura come illustrato alla fine della mia domanda. E come già sottolineato dall'utente20650, il semplice scambio delle due variabili di faccette nella formula risolve il problema. Ho presentato una segnalazione di bug. – barbaz

+0

@barbaz Ho cercato di spiegare che questo non è un bug e funziona come previsto, e perché hai ottenuto diversi assi xey nell'usare sfaccettature in quell'ordine (che era la discussione nei commenti, una spiegazione di questo comportamento). Una volta invertito l'ordine delle faccette, ottenere la figura come hai mostrato è una questione di riorganizzare le righe - Ho aggiornato la risposta con maggiori dettagli – konvas

+1

Ciao Konvas, penso che tu possa ottenere l'ordine dei pannelli usando 'come .table' argomento ... 'facet_grid (facetB ~ facetA, scale =" free ", as.table = FALSE)' – user20650