2013-06-13 9 views
11

I grafici di dispersione possono essere difficili da interpretare quando molti punti si sovrappongono, poiché tale sovrapposizione oscura la densità dei dati in una particolare regione. Una soluzione consiste nell'utilizzare colori semitrasparenti per i punti tracciati, in modo che la regione opaca indichi che molte osservazioni sono presenti in quelle coordinate.Grafico a dispersione R: il colore simbolo rappresenta il numero di punti sovrapposti

Di seguito è riportato un esempio della mia soluzione in bianco e nero in R:

MyGray <- rgb(t(col2rgb("black")), alpha=50, maxColorValue=255) 
x1 <- rnorm(n=1E3, sd=2) 
x2 <- x1*1.2 + rnorm(n=1E3, sd=2) 
dev.new(width=3.5, height=5) 
par(mfrow=c(2,1), mar=c(2.5,2.5,0.5,0.5), ps=10, cex=1.15) 
plot(x1, x2, ylab="", xlab="", pch=20, col=MyGray) 
plot(x1, x2, ylab="", xlab="", pch=20, col="black") 

The advantages of using opacity to indicate point density

Tuttavia, di recente mi sono imbattuto in this article in PNAS, che ha preso un un approccio simile, ma abituato al calore mappa colorazione in contrasto con l'opacità come indicatore di quanti punti si sovrapponevano. L'articolo è Open Access, quindi chiunque può scaricare il file .pdf e guardare la Figura 1, che contiene un esempio pertinente del grafico che voglio creare. La sezione dei metodi di questo documento indica che le analisi sono state fatte in Matlab.

Per motivi di convenienza, ecco una piccola porzione di figura 1 dal suddetto articolo:

Figure 1 from Flombaum et al. 2013, PNAS

Come faccio a creare un grafico a dispersione in R che ha usato il colore, non è l'opacità, come indicatore della densità del punto?

Per gli utenti iniziali, gli utenti R possono accedere a questa combinazione di colori Matlab nella libreria install.packages("fields"), utilizzando la funzione tim.colors().

Esiste un modo semplice per ottenere una figura simile alla Figura 1 del precedente articolo, ma in R? Grazie!

risposta

26

Un'opzione è utilizzare densCols() per estrarre la densità del kernel in ogni punto. Mappando tali densità alla rampa cromatica desiderata e tracciando i punti in ordine di aumento della densità locale si ottiene una trama molto simile a quella dell'articolo collegato.

## Data in a data.frame 
x1 <- rnorm(n=1E3, sd=2) 
x2 <- x1*1.2 + rnorm(n=1E3, sd=2) 
df <- data.frame(x1,x2) 

## Use densCols() output to get density at each point 
x <- densCols(x1,x2, colramp=colorRampPalette(c("black", "white"))) 
df$dens <- col2rgb(x)[1,] + 1L 

## Map densities to colors 
cols <- colorRampPalette(c("#000099", "#00FEFF", "#45FE4F", 
          "#FCFF00", "#FF9400", "#FF3100"))(256) 
df$col <- cols[df$dens] 

## Plot it, reordering rows so that densest points are plotted on top 
plot(x2~x1, data=df[order(df$dens),], pch=20, col=col, cex=2) 

enter image description here

+0

+10 Potrei votare ancora più in alto se potessi. –

+0

Questo sembra essere esattamente la risposta che speravo ... grazie! – rbatt

+0

@JoshOBrien: è fantastico! Due domande: 1) Come sei riuscito ad aggiungere l'immagine qui nella tua risposta? 2) Come aggiungere una legenda qui? – Shambho

3

Per questo è possibile utilizzare smoothScatter.

colramp = colorRampPalette(c('white', 'blue', 'green', 'yellow', 'red')) 
smoothScatter(x1, x2, colramp=colramp) 
+0

Grazie per la risposta - Si tratta di circa l'idea giusta, ma mi piacerebbe evitare il livellamento dei punti. Ho provato a giocare con la larghezza di banda, ecc, ma non sembra che questa funzione sarà in grado di mantenere punti individuali. – rbatt

+0

Bella scoperta! Non sapevo nulla di questa o della relativa funzione 'densCols()' che ho usato nella mia risposta proprio ora. –

5

È possibile ottenere un effetto simile facendo binning esagonale, dividere la regione in esagoni, colore ogni esagono in base al numero di punti dell'esagono. Il pacchetto hexbin ha funzioni per farlo e ci sono anche funzioni nel pacchetto ggplot2.

+1

Che funzione fa in ggplot2? – rbatt

+0

@rbatt, guarda 'stat_binhex'. –