2012-07-22 729 views
12

Tengo bastante tiempo para comprender geom_bar() y position="dodge". Estaba tratando de hacer algunos gráficos de barras que ilustran dos grupos. Originalmente, los datos eran de dos marcos de datos separados. Por this question, puse mis datos en formato largo. Mi ejemplo:Problema con ggplot2, geom_bar, y position = "dodge": apilado tiene valores y correctos, esquivado no

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)) 

Utilizo ese ejemplo, ya que es similar al ejemplo de gasto versus presupuesto. El gasto tiene muchas filas por names nivel de factor, mientras que el presupuesto solo tiene uno (un monto de presupuesto por categoría).

Para un gráfico de barras apiladas, esto funciona muy bien:

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

stacked plot

En particular, tenga en cuenta el valor y maximiza. Son las sumas de los datos de test con los valores de test2 que se muestran en azul en la parte superior.

Basándonos en las otras preguntas que he leído, que sólo tendrá que añadir position="dodge" para que sea una parcela de lado a lado contra un apilados uno:

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

dodged

Se ve muy bien , pero tenga en cuenta los nuevos valores máximos y. Parece que solo está tomando el valor máximo y de cada nivel de factor de nombre de test para el valor y. Ya no los está sumando.

por algunas otras cuestiones (como this one y this one, también intentado añadir la opción group= sin éxito (produce la misma parcela esquivado que el anterior):

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

No entiendo por qué el apilado grandes obras y la esquivado no sólo los puso al lado del otro en lugar de en la parte superior


ETA:. encontré una recent question sobre esto en el ggplot google group con la sugerencia de agregar alpha=0.5 para ver qué está pasando. No es que ggplot tome el valor máximo de cada agrupación; en realidad está sobre-trazando barras una encima de la otra para cada valor.

Parece que al usar position="dodge", ggplot espera solo una y por x. Me puse en contacto con Winston Chang, un desarrollador de ggplot, para confirmarlo y para saber si esto puede cambiarse ya que no veo una ventaja.

Parece que stat="identity" debería decir ggplot a contar el y=val pasa dentro aes() en lugar de conteos individuales que sucede sin stat="identity" y al pasar ningún valor y.

Por ahora, la solución parece ser (para los df originales arriba) para agregar de manera que sólo hay una y por 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

Respuesta

16

Creo que el problema es que desea pila dentro de valores del grupo num, y esquivar entre valores de num. Puede ser útil observar lo que sucede cuando agrega un contorno a las barras.

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) 
) 

Por defecto, hay una gran cantidad de barras apiladas - simplemente no se vea que están separados a menos que tenga un contorno:

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

Stacked bars

Si esquivar , obtiene barras que se esquivan entre los valores de num, pero puede haber varias barras dentro de cada valor de 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

Si también agrega id como var agrupación, que va a esquivar todos ellos:

# 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

Creo que lo que quiere es tanto esquiva y la pila, pero no puedes hacer ambas cosas. Así que lo mejor es resumir los datos usted mismo.

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

que tenemos. Fue bastante útil para ti señalar que en realidad estoy pidiendo esquivar y apilar. Una objeción: cuando no se usa 'stat =" identity "' (así que básicamente se hace un histograma), ¿no se "apila" el ggplot los conteos individuales mientras se elude entre alguna otra característica? Aun así, estoy de acuerdo con la respuesta de que así es como funciona en este momento. ¡Pensé que estaba haciendo algo mal en mi código! – Hendy

+2

'geom_bar' puede ser un poco confuso porque se usa para dos propósitos diferentes: a veces se usa para trazar los valores y que usted proporciona, y algunas veces cuenta el número de casos en cada uno y usa ese valor como el valor y (con' stat = "bin" '). El último comportamiento es el predeterminado (se puede ver con 'ggplot (df, aes (x = factor (nombres), fill = factor (num))) + geom_bar (color =" black ")'). En este caso, el "apilamiento" no es el mismo: es un resumen _stat_, mientras que el apilamiento habitual es un _posición de ajuste_. Estas cosas suceden en diferentes etapas de la tubería ggplot. – wch

+0

Gracias por la explicación. La agregación no es un gran problema y ahora sé que necesito hacerlo, lo cual es un gran paso desde el simple hecho de estar confundido :) – Hendy

Cuestiones relacionadas