Scatterplot con istogrammi marginali in ggplot2

C’è un modo per creare grafici a dispersione con istogrammi marginali proprio come nell’esempio qui sotto in ggplot2 ? In Matlab è la funzione scatterhist() e esistono anche equivalenti per R. Tuttavia, non l’ho visto per ggplot2.

scatterplot con istogrammi marginali

Ho iniziato un tentativo creando i singoli grafici ma non so come sistemarli correttamente.

  require(ggplot2) x<-rnorm(300) y<-rt(300,df=2) xy<-data.frame(x,y) xhist <- qplot(x, geom="histogram") + scale_x_continuous(limits=c(min(x),max(x))) + opts(axis.text.x = theme_blank(), axis.title.x=theme_blank(), axis.ticks = theme_blank(), aspect.ratio = 5/16, axis.text.y = theme_blank(), axis.title.y=theme_blank(), background.colour="white") yhist <- qplot(y, geom="histogram") + coord_flip() + opts(background.fill = "white", background.color ="black") yhist <- yhist + scale_x_continuous(limits=c(min(x),max(x))) + opts(axis.text.x = theme_blank(), axis.title.x=theme_blank(), axis.ticks = theme_blank(), aspect.ratio = 16/5, axis.text.y = theme_blank(), axis.title.y=theme_blank() ) scatter <- qplot(x,y, data=xy) + scale_x_continuous(limits=c(min(x),max(x))) + scale_y_continuous(limits=c(min(y),max(y))) none <- qplot(x,y, data=xy) + geom_blank() 

e disponendoli con la funzione pubblicata qui . Ma per farla breve: esiste un modo per creare questi grafici?

Il pacchetto gridExtra dovrebbe funzionare qui. Inizia facendo ciascuno degli oggetti ggplot:

 hist_top < - ggplot()+geom_histogram(aes(rnorm(100))) empty <- ggplot()+geom_point(aes(1,1), colour="white")+ theme(axis.ticks=element_blank(), panel.background=element_blank(), axis.text.x=element_blank(), axis.text.y=element_blank(), axis.title.x=element_blank(), axis.title.y=element_blank()) scatter <- ggplot()+geom_point(aes(rnorm(100), rnorm(100))) hist_right <- ggplot()+geom_histogram(aes(rnorm(100)))+coord_flip() 

Quindi utilizzare la funzione grid.arrange:

 grid.arrange(hist_top, empty, scatter, hist_right, ncol=2, nrow=2, widths=c(4, 1), heights=c(1, 4)) 

tracciare

Questa non è una risposta completamente retriggers, ma è molto semplice. Illustra un metodo alternativo per visualizzare le densità marginali e anche come utilizzare i livelli alfa per l’output grafico che supporta la trasparenza:

 scatter < - qplot(x,y, data=xy) + scale_x_continuous(limits=c(min(x),max(x))) + scale_y_continuous(limits=c(min(y),max(y))) + geom_rug(col=rgb(.5,0,0,alpha=.2)) scatter 

inserisci la descrizione dell'immagine qui

Questo potrebbe essere un po ‘in ritardo, ma ho deciso di creare un pacchetto ( ggExtra ) per questo poiché implicava un po’ di codice e può essere noioso da scrivere. Il pacchetto cerca anche di risolvere alcuni problemi comuni, ad esempio assicurando che, anche se è presente un titolo o il testo sia ingrandito, i grafici saranno ancora allineati l’uno con l’altro.

L’idea di base è simile a ciò che hanno dato le risposte, ma va un po ‘oltre. Ecco un esempio di come aggiungere istogrammi marginali a un insieme casuale di 1000 punti. Speriamo che questo faciliti l’aggiunta di grafici di istogrammi / densità in futuro.

Link al pacchetto ggExtra

 library(ggplot2) df < - data.frame(x = rnorm(1000, 50, 10), y = rnorm(1000, 50, 10)) p <- ggplot(df, aes(x, y)) + geom_point() + theme_classic() ggExtra::ggMarginal(p, type = "histogram") 

inserisci la descrizione dell'immagine qui

Un’aggiunta, giusto per risparmiare un po ‘di tempo in cerca di persone che fanno questo dopo di noi.

Leggende, etichette degli assi, testi degli assi, zecche fanno sì che le trame si allontanino l’una dall’altra, quindi la trama sembrerà brutta e incoerente.

Puoi correggere questo usando alcune di queste impostazioni del tema,

 +theme(legend.position = "none", axis.title.x = element_blank(), axis.title.y = element_blank(), axis.text.x = element_blank(), axis.text.y = element_blank(), plot.margin = unit(c(3,-5.5,4,3), "mm")) 

e allineare le scale,

 +scale_x_continuous(breaks = 0:6, limits = c(0,6), expand = c(.05,.05)) 

quindi i risultati sembreranno OK:

un esempio

Solo una piccola variazione sulla risposta di BondedDust , nello spirito generale degli indicatori marginali di distribuzione.

Edward Tufte ha definito questo uso dei diagrammi di tappeto un “diagramma a punti”, e ha un esempio in VDQI di usare le linee degli assi per indicare l’intervallo di ciascuna variabile. Nel mio esempio le etichette degli assi e le linee della griglia indicano anche la distribuzione dei dati. Le etichette si trovano ai valori del riepilogo dei cinque numeri di Tukey (minimo, cerniera inferiore, mediana, cerniera superiore, massimo), dando una rapida impressione della diffusione di ciascuna variabile.

Questi cinque numeri sono quindi una rappresentazione numerica di un boxplot. È un po ‘complicato perché le linee della griglia distanziate in modo non uniforms suggeriscono che gli assi hanno una scala non lineare (in questo esempio sono lineari). Forse sarebbe meglio omettere le linee della griglia o forzarle in luoghi regolari e lasciare che le etichette mostrino il riepilogo dei cinque numeri.

 x< -rnorm(300) y<-rt(300,df=10) xy<-data.frame(x,y) require(ggplot2); require(grid) # make the basic plot object ggplot(xy, aes(x, y)) + # set the locations of the x-axis labels as Tukey's five numbers scale_x_continuous(limit=c(min(x), max(x)), breaks=round(fivenum(x),1)) + # ditto for y-axis labels scale_y_continuous(limit=c(min(y), max(y)), breaks=round(fivenum(y),1)) + # specify points geom_point() + # specify that we want the rug plot geom_rug(size=0.1) + # improve the data/ink ratio theme_set(theme_minimal(base_size = 18)) 

inserisci la descrizione dell'immagine qui

Poiché non c’era alcuna soluzione soddisfacente per questo tipo di trama quando si confrontano gruppi diversi, ho scritto una funzione per farlo.

Funziona sia per i dati raggruppati che per quelli non raggruppati e accetta parametri grafici aggiuntivi:

 marginal_plot(x = iris$Sepal.Width, y = iris$Sepal.Length) 

inserisci la descrizione dell'immagine qui

 marginal_plot(x = Sepal.Width, y = Sepal.Length, group = Species, data = iris, bw = "nrd", lm_formula = NULL, xlab = "Sepal width", ylab = "Sepal length", pch = 15, cex = 0.5) 

inserisci la descrizione dell'immagine qui

Ho trovato il pacchetto ( ggpubr ) che sembra funzionare molto bene per questo problema e considera diverse possibilità per visualizzare i dati.

Il link al pacchetto è qui , e in questo link troverai un bel tutorial per usarlo. Per completezza, allego uno degli esempi che ho riprodotto.

Per prima cosa ho installato il pacchetto (richiede devtools )

 if(!require(devtools)) install.packages("devtools") devtools::install_github("kassambara/ggpubr") 

Per l’esempio particolare di visualizzazione di istogrammi diversi per gruppi diversi, si menziona in relazione con ggExtra : “Una limitazione di ggExtra è che non può far fronte a più gruppi nel ggExtra a dispersione e nei grafici marginali. fornire una soluzione utilizzando il pacchetto cowplot . ” Nel mio caso, ho dovuto installare il secondo pacchetto:

 install.packages("cowplot") 

E ho seguito questo pezzo di codice:

 # Scatter plot colored by groups ("Species") sp < - ggscatter(iris, x = "Sepal.Length", y = "Sepal.Width", color = "Species", palette = "jco", size = 3, alpha = 0.6)+ border() # Marginal density plot of x (top panel) and y (right panel) xplot <- ggdensity(iris, "Sepal.Length", fill = "Species", palette = "jco") yplot <- ggdensity(iris, "Sepal.Width", fill = "Species", palette = "jco")+ rotate() # Cleaning the plots sp <- sp + rremove("legend") yplot <- yplot + clean_theme() + rremove("legend") xplot <- xplot + clean_theme() + rremove("legend") # Arranging the plot using cowplot library(cowplot) plot_grid(xplot, NULL, sp, yplot, ncol = 2, align = "hv", rel_widths = c(2, 1), rel_heights = c(1, 2)) 

Che ha funzionato bene per me:

Iris imposta lo scatterplot degli istogrammi marginali

inserisci la descrizione dell'immagine qui

Puoi facilmente creare interessanti grafici a dispersione con istogrammi marginali usando ggstatsplot (si adatta anche e descrive un modello):

 data(iris) library(ggstatsplot) ggscatterstats( data = iris, x = Sepal.Length, y = Sepal.Width, xlab = "Sepal Length", ylab = "Sepal Width", marginal = TRUE, marginal.type = "histogram", centrality.para = "mean", margins = "both", title = "Relationship between Sepal Length and Sepal Width", messages = FALSE ) 

inserisci la descrizione dell'immagine qui

O leggermente più attraente (di default) ggpubr :

 devtools::install_github("kassambara/ggpubr") library(ggpubr) ggscatterhist( iris, x = "Sepal.Length", y = "Sepal.Width", color = "Species", # comment out this and last line to remove the split by species margin.plot = "histogram", # I'd suggest removing this line to get density plots margin.params = list(fill = "Species", color = "black", size = 0.2) ) 

inserisci la descrizione dell'immagine qui

AGGIORNARE:

Come suggerito da @aickley, ho usato la versione di sviluppo per creare la trama.