2012-02-29 15 views
15

me he encontrado con un problema interesante con escalamiento utilizando ggplot. Tengo un conjunto de datos que puedo graficar bien utilizando la escala lineal predeterminada, pero cuando uso scale_y_log10() los números van muy lejos. Aquí hay un código de ejemplo y dos imágenes. Tenga en cuenta que el valor máximo en la escala lineal es ~ 700, mientras que la escala de registro da como resultado un valor de 10^8. Te muestro que todo el conjunto de datos tiene solo ~ 8000 entradas, por lo que algo no está bien.scale_y_log10 ggplot() tema

Me imagino que el problema tiene que ver con la estructura de mi conjunto de datos y el hurgar en la basura ya que no puedo reproducir este error en un conjunto de datos comunes como 'diamantes'. Sin embargo, no estoy seguro de la mejor manera de solucionar problemas.

gracias, zach cp


Editar: bdamarest puede reproducir el problema de escala en el conjunto de datos de diamantes de la siguiente manera:

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

aquí hay algunos datos de ejemplo ... y creo que veo el problema. El conjunto de datos original fundido puede tener ~ 10^8 filas de largo. Tal vez los números de fila se están utilizando para las estadísticas?

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

ACTUALIZACIÓN:

Los números de fila no son el problema. Aquí son los mismos datos graficados utilizando el mismo aes eje X y llenan de color y la escala es del todo correcto:

> 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

Respuesta

24

geom_bar y scale_y_log10 (o cualquier escala logarítmica) no funcionan bien juntos y no dan los resultados esperados.

El primer problema fundamental es que las barras van a 0, y en una escala logarítmica, 0 se transforma hasta el infinito negativo (que es difícil de trazar). La cuna alrededor de esto generalmente comienza en 1 en lugar de 0 (desde $ \ log (1) = 0 $), no traza nada si hubo 0 conteos, y no se preocupa por la distorsión porque si se necesita una escala de logs probablemente 't se preocupan por estar fuera de 1 (no necesariamente cierto, pero ...)

Estoy usando el ejemplo diamonds que mostró @dbemarest.

Para hacer esto en general es transformar las coordenadas, no la escala (más en la diferencia más adelante).

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

Pero esto da un error

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

que surge del problema infinito negativo.

Cuando utiliza una transformación de escala, la transformación se aplica a los datos, luego se realizan las estadísticas y las disposiciones, luego las escalas se etiquetan en la transformación inversa (más o menos). Puede ver lo que está sucediendo al hacer los cálculos usted mismo.

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

lo que da

> 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 

Si graficamos esto en la forma normal, obtenemos el diagrama de barras esperado:

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

enter image description here

y escalar el eje y da el mismo problema que usar los datos no pre-resumidos.

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

enter image description here

Podemos ver cómo el problema pasa por el trazado de las log10() valores de los recuentos.

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

enter image description here

Esto se parece a la que tiene el scale_y_log10, pero las etiquetas son 0, 5, 10, ... en lugar de 10^0, 10^5, 10^10,. ..

Por lo que usar scale_y_log10 hace los recuentos, los convierte en registros, los apila y luego muestra la escala en el formulario anti-registro. Sin embargo, el apilamiento de registros no es una transformación lineal, por lo que lo que le pediste que haga no tiene ningún sentido.

La conclusión es que los gráficos de barras apiladas en una escala de registro no tienen mucho sentido porque no pueden comenzar en 0 (donde debería estar la parte inferior de una barra) y comparar partes de la barra no es razonable porque su tamaño depende de dónde están en la pila. Considerado en su lugar algo así como:

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

enter image description here

O si realmente quieres un total para los grupos que apilar las barras normalmente se le dará, puede hacer algo como:

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

gracias Brian, le agradezco la explicación detallada. También puede usar geom_bar (position = "dodge") (respuesta cortesía de Winston Chang) – zach

+0

Para dar un poco más de información sobre lo que está sucediendo aquí, los gráficos de barras apiladas generalmente le dan una altura de barra igual a la suma de conteos. Sin embargo, sum (log (counts)) es equivalente a log (product (counts)). En otras palabras, verá alturas de barra como si multiplicara los recuentos juntos. – Brian