2012-07-22 12 views
12

Sto avendo abbastanza tempo a capire geom_bar() e position="dodge". Stavo cercando di creare dei grafici a barre che illustrassero due gruppi. Originariamente i dati provenivano da due frame di dati separati. Per this question, ho inserito i miei dati nel formato lungo. Il mio esempio:Problema con ggplot2, geom_bar e position = "dodge": impilato ha valori y corretti, evitato non

test <- data.frame(names=rep(c("A","B","C"), 5), values=1:15) 
test2 <- data.frame(names=c("A","B","C"), values=5:7) 

df <- data.frame(names=c(paste(test$names), paste(test2$names)), num=c(rep(1, 
nrow(test)), rep(2, nrow(test2))), values=c(test$values, test2$values)) 

Io uso questo esempio poiché è simile all'esempio di spesa rispetto al budget. La spesa ha molte righe per livello di fattore names mentre il budget ha solo uno (un importo di budget per categoria).

Per un grafico a barre in pila, questo funziona grande:

ggplot(df, aes(x=factor(names), y=values, fill=factor(num))) + 
geom_bar(stat="identity") 

stacked plot

In particolare, notare il valore y maxes. Sono le somme dei dati da test con i valori di test2 mostrati in blu in alto.

Sulla base di altre questioni che ho letto, ho semplicemente bisogno di aggiungere position="dodge" per renderlo un complotto side-by-side contro un impilati uno:

ggplot(df, aes(x=factor(names), y=values, fill=factor(num))) + 
geom_bar(stat="identity", position="dodge") 

dodged

sembra grande , ma nota i nuovi valori max y. Sembra che stia prendendo il massimo valore da ciascun livello di fattore nomi da test per il valore y. Non li sta più riassumendo.

Per altre domande (come this one e this one, ho anche provato ad aggiungere l'opzione group= senza successo (produce la stessa trama schivato come sopra):

ggplot(df, aes(x=factor(names), y=values, fill=factor(num), group=factor(num))) + 
geom_bar(stat="identity", position="dodge") 

Non capisco perché il impilate grandi opere e il schivato non significa solo mettere fianco a fianco invece che in cima


ETA:. ho trovato un recent question su questo sul ggplot google group con il suggerimento di aggiungere alpha=0.5 per vedere cosa sta succedendo. Non è che ggplot stia prendendo il valore massimo da ogni gruppo; in realtà si sovrappongono le barre l'una sopra l'altra per ciascun valore.

Sembra che quando si utilizza position="dodge", ggplot si aspetta solo un y per x. Ho contattato Winston Chang, uno sviluppatore di ggplot per confermare questo e per sapere se questo può essere modificato in quanto non vedo un vantaggio.

Sembra che stat="identity" dovrebbe dire ggplot coincidere il y=val passato all'interno aes() anziché singoli conteggi che avviene senza stat="identity" e quando passa alcun valore y.

Per il momento, la soluzione sembra essere (per il df originale sopra) di aggregare in modo non c'è un solo y per ogni x:

df2 <- aggregate(df$values, by=list(df$names, df$num), FUN=sum) 
p <- ggplot(df2, aes(x=Group.1, y=x, fill=factor(Group.2))) 
p <- p + geom_bar(stat="identity", position="dodge") 
p 

correct

risposta

16

Credo che il problema è che si vuole impilare all'interno dei valori del gruppo num e schivare tra valori di num. Potrebbe aiutare a vedere cosa succede quando aggiungi un contorno alle barre.

library(ggplot2) 
set.seed(123) 
df <- data.frame(
    id  = 1:18, 
    names = rep(LETTERS[1:3], 6), 
    num = c(rep(1, 15), rep(2, 3)), 
    values = sample(1:10, 18, replace=TRUE) 
) 

Per impostazione predefinita, ci sono un sacco di bar stacked - basta non vedere che sono separati a meno che non si dispone di un contorno:

# Stacked bars 
ggplot(df, aes(x=factor(names), y=values, fill=factor(num))) + 
    geom_bar(stat="identity", colour="black") 

Stacked bars

Se schivare , ottieni barre evitate tra i valori di num, ma potrebbero esserci più barre all'interno di ciascun valore di num:

# Dodged on 'num', but some overplotted bars 
ggplot(df, aes(x=factor(names), y=values, fill=factor(num))) + 
    geom_bar(stat="identity", colour="black", position="dodge", alpha=0.1) 

Dodged on num

Se si aggiunge anche id come var raggruppamento, sarà schivare tutti loro:

# Dodging with unique 'id' as the grouping var 
ggplot(df, aes(x=factor(names), y=values, fill=factor(num), group=factor(id))) + 
    geom_bar(stat="identity", colour="black", position="dodge", alpha=0.1) 

Dodge all bars

Penso che ciò che si desidera è di entrambi schivare e Stack, ma non puoi fare entrambe le cose. Quindi la cosa migliore è riassumere i dati da soli.

library(plyr) 
df2 <- ddply(df, c("names", "num"), summarise, values = sum(values)) 

ggplot(df2, aes(x=factor(names), y=values, fill=factor(num))) + 
    geom_bar(stat="identity", colour="black", position="dodge") 

Summarized beforehand

+0

ottenuto. È stato abbastanza utile per te sottolineare che in realtà sto chiedendo sia di schivare che di impilare. Un cavillo: quando non si usa 'stat =" identity "' (in pratica facendo un istogramma), non ggplot "impila" i singoli conteggi mentre si scansa tra alcune altre caratteristiche? Anche così, sto bene con la risposta che è proprio come funziona al momento. Pensavo di fare qualcosa di sbagliato nel mio codice! – Hendy

+2

'geom_bar' può essere un po 'confuso perché è usato per due scopi diversi: a volte è usato per tracciare y valori che tu fornisci, ea volte conta il numero di casi in ciascuno e usa quel valore come valore y (con' stat = "bin" '). Il secondo comportamento è quello predefinito (puoi vederlo con 'ggplot (df, aes (x = fattore (nomi), fill = factor (num))) + geom_bar (color =" black ")'). In questo caso, lo "stacking" non è esattamente lo stesso: è un riepilogo _stat_, mentre il solito stacking è un _position adjustment_. Queste cose accadono nelle diverse fasi della pipeline di ggplot. – wch

+0

Grazie per la spiegazione. L'aggregazione non è un grosso problema e ora so che ne ho bisogno, il che è un grande passo dopo essere stato confuso :) – Hendy

Problemi correlati