2012-02-29 16 views
15

Ho riscontrato un problema interessante con il ridimensionamento utilizzando ggplot. Ho un set di dati che posso tracciare bene usando la scala lineare di default, ma quando uso scale_y_log10() i numeri vanno via. Ecco alcuni esempi di codice e due immagini. Notare che il valore massimo nella scala lineare è ~ 700 mentre il ridimensionamento del registro ha un valore di 10^8. Ti mostro che l'intero set di dati è lungo solo ~ 8000 voci, quindi qualcosa non va bene.ggplot scale_y_log10() problema

Immagino che il problema abbia a che fare con la struttura del mio set di dati e il binning poiché non riesco a replicare questo errore su un set di dati comune come "diamanti". Tuttavia non sono sicuro che sia il modo migliore per risolvere i problemi.

grazie, Zach CP


Edit: bdamarest in grado di riprodurre il problema scala sul set di dati di diamante in questo modo:

example_1 = ggplot(diamonds, aes(x=clarity, fill=cut)) + 
    geom_bar() + scale_y_log10(); print(example_1) 

#data.melt is the name of my dataset  
> ggplot(data.melt, aes(name, fill= Library)) + geom_bar() 
> ggplot(data.melt, aes(name, fill= Library)) + geom_bar() + scale_y_log10() 
> length(data.melt$name) 
[1] 8003 

linear scale log scale

ecco alcuni dati di esempio ... e penso di vedere il problema. Il set di dati fuso originale poteva essere lungo ~ 10^8 righe. Forse i numeri di riga vengono utilizzati per le statistiche?

> head(data.melt) 
     Library   name    group 
221938  AB Arthrofactin  glycopeptide 
235087  AB Putisolvin  cyclic peptide 
235090  AB Putisolvin  cyclic peptide 
222125  AB Arthrofactin  glycopeptide 
311468  AB  Triostin cyclic depsipeptide 
92249  AB   CDA   lipopeptide 


> dput(head(test2)) 
structure(list(Library = c("AB", "AB", "AB", "AB", "AB", "AB" 
), name = c("Arthrofactin", "Putisolvin", "Putisolvin", "Arthrofactin", 
"Triostin", "CDA"), group = c("glycopeptide", "cyclic peptide", 
"cyclic peptide", "glycopeptide", "cyclic depsipeptide", "lipopeptide" 
)), .Names = c("Library", "name", "group"), row.names = c(221938L, 
235087L, 235090L, 222125L, 311468L, 92249L), class = "data.frame") 

UPDATE:

numeri di riga non sono il problema. Ecco gli stessi dati graficamente utilizzando gli stessi AES asse xe colore di riempimento e la scala è del tutto corretto:

> ggplot(data.melt, aes(name, fill= name)) + geom_bar() 
> ggplot(data.melt, aes(name, fill= name)) + geom_bar() + scale_y_log10() 
> length(data.melt$name) 
[1] 8003 

enter image description here enter image description here

risposta

24

geom_bar e scale_y_log10 (o qualsiasi scala logaritmica) non funzionano bene insieme e non dare risultati attesi.

Il primo problema fondamentale è che le barre vanno a 0, e su una scala logaritmica, 0 viene trasformato in infinito negativo (che è difficile da tracciare). La greppia attorno a questo di solito inizia da 1 piuttosto che da 0 (poiché $ \ log (1) = 0 $), non traccia nulla se ci sono 0 conteggi, e non ti preoccupare della distorsione perché se è necessaria una scala di log probabilmente non Non mi interessa essere spenti di 1 (non necessariamente vero, ma ...)

Sto usando l'esempio diamonds mostrato da @dbemarest.

Per fare questo in generale è quello di trasformare la coordinata, non la scala (più sulla differenza in seguito).

ggplot(diamonds, aes(x=clarity, fill=cut)) + 
    geom_bar() + 
    coord_trans(ytrans="log10") 

Ma questo produce un errore

Error in if (length(from) == 1 || abs(from[1] - from[2]) < 1e-06) return(mean(to)) : 
    missing value where TRUE/FALSE needed 

derivante dal problema infinito negativo.

Quando si utilizza una trasformazione di scala, la trasformazione viene applicata ai dati, quindi vengono eseguite le statistiche e le disposizioni, quindi le scale vengono etichettate nella trasformazione inversa (approssimativamente). Puoi vedere cosa sta succedendo scoppiando i calcoli tu stesso.

DF <- ddply(diamonds, .(clarity, cut), summarise, n=length(clarity)) 
DF$log10n <- log10(DF$n) 

che dà

> head(DF) 
    clarity  cut n log10n 
1  I1  Fair 210 2.322219 
2  I1  Good 96 1.982271 
3  I1 Very Good 84 1.924279 
4  I1 Premium 205 2.311754 
5  I1  Ideal 146 2.164353 
6  SI2  Fair 466 2.668386 

Se tracciamo questo nel modo normale, si ottiene la barra di trama atteso:

ggplot(DF, aes(x=clarity, y=n, fill=cut)) + 
    geom_bar(stat="identity") 

enter image description here

e scalare l'asse y dà lo stesso problema con l'utilizzo dei dati non pre-riassunti.

ggplot(DF, aes(x=clarity, y=n, fill=cut)) + 
    geom_bar(stat="identity") + 
    scale_y_log10() 

enter image description here

Possiamo vedere come il problema si verifica tracciando i valori log10() dei conti.

ggplot(DF, aes(x=clarity, y=log10n, fill=cut)) + 
    geom_bar(stat="identity") 

enter image description here

Questo sembra proprio come quello con il scale_y_log10, ma le etichette sono 0, 5, 10, ... invece di 10^0, 10^5, 10^10,. ..

Quindi l'utilizzo di scale_y_log10 esegue i conteggi, li converte in registri, impila questi registri e quindi visualizza la scala nel modulo anti-registro. Tuttavia, i registri di impilamento non sono una trasformazione lineare, quindi ciò che gli hai chiesto di fare non ha alcun senso.

La linea di fondo è che i grafici a barre in pila su una scala di registro non hanno molto senso perché non possono iniziare a 0 (dove dovrebbe essere il fondo di una barra) e confrontare le parti della barra non è ragionevole perché la loro dimensione dipende da dove si trovano nella pila. Considerato invece qualcosa di simile:

ggplot(diamonds, aes(x=clarity, y=..count.., colour=cut)) + 
    geom_point(stat="bin") + 
    scale_y_log10() 

enter image description here

Oppure, se si vuole veramente un totale per i gruppi che accatastamento le barre di solito darebbe, si può fare qualcosa di simile:

ggplot(diamonds, aes(x=clarity, y=..count..)) + 
    geom_point(aes(colour=cut), stat="bin") + 
    geom_point(stat="bin", colour="black") + 
    scale_y_log10() 

enter image description here

+1

grazie Brian, apprezzo la tua spiegazione dettagliata. Puoi anche utilizzare geom_bar (position = "dodge") (risposta per gentile concessione di Winston Chang) – zach

+0

Per dare un po 'di più informazioni su ciò che sta accadendo qui, i grafici a barre in pila ti danno generalmente un'altezza di barra uguale alla somma dei conteggi. Tuttavia, sum (log (conteggi)) equivale a log (prodotto (conteggi)). In altre parole, vedrai le altezze come se moltiplichi i conteggi insieme. – Brian