Transformar sólo uno de los ejes a escala log10 con ggplot2
-
11-10-2019 - |
Pregunta
Tengo el siguiente problema: Me gustaría visualizar un discreto y una variable continua en un diagrama de caja en el que el último tiene unos valores extremos altos. Esto hace que el sentido diagrama de caja (los puntos e incluso el "cuerpo" de la tabla es demasiado pequeño), es por eso que me gustaría mostrar esto en una escala log10. Soy consciente de que yo pudiera dejar de lado los valores extremos de la visualización, pero no me proponía.
Vamos a ver un ejemplo sencillo con los datos de los diamantes:
m <- ggplot(diamonds, aes(y = price, x = color))
El problema no es serio aquí, pero espero que se pueda imaginar por qué me gustaría ver los valores en una escala log10. Vamos a intentarlo:
m + geom_boxplot() + coord_trans(y = "log10")
Como se puede ver el eje y es log10 escalado y se ve bien, pero hay un problema con el eje x, lo que hace que la trama muy extraño.
El problema no se produce con scale_log
, pero esto no es una opción para mí , ya que no puedo utilizar una costumbre formateador de esta manera. Por ejemplo:.
m + geom_boxplot() + scale_y_log10()
Mi pregunta: ¿alguien sabe una solución para trazar la gráfica de caja con la escala log10 en el eje y las etiquetas que pudieran presentarse libremente con una función formatter
como en este hilo ?
Edición de la pregunta a la que responden de ayuda basados ??en las respuestas y comentarios:
Lo que estoy realmente después: un eje transformado log10 (y) con las etiquetas no científicas. Me gustaría etiquetarlo como (formatter=dollar)
dólar o cualquier formato personalizado.
Si intento sugerencia de @ Hadley consigo las advertencias siguientes:
> m + geom_boxplot() + scale_y_log10(formatter=dollar)
Warning messages:
1: In max(x) : no non-missing arguments to max; returning -Inf
2: In max(x) : no non-missing arguments to max; returning -Inf
3: In max(x) : no non-missing arguments to max; returning -Inf
Con una y sin cambios eje etiquetas:
Solución
The simplest is to just give the 'trans' (formerly 'formatter' argument the name of the log function:
m + geom_boxplot() + scale_y_continuous(trans='log10')
EDIT: Or if you don't like that, then either of these appears to give different but useful results:
m <- ggplot(diamonds, aes(y = price, x = color), log="y")
m + geom_boxplot()
m <- ggplot(diamonds, aes(y = price, x = color), log10="y")
m + geom_boxplot()
EDIT2 & 3: Further experiments (after discarding the one that attempted successfully to put "$" signs in front of logged values):
fmtExpLg10 <- function(x) paste(round_any(10^x/1000, 0.01) , "K $", sep="")
ggplot(diamonds, aes(color, log10(price))) +
geom_boxplot() +
scale_y_continuous("Price, log10-scaling", trans = fmtExpLg10)
Note added mid 2017 in comment about package syntax change:
scale_y_continuous(formatter = 'log10') is now scale_y_continuous(trans = 'log10') (ggplot2 v2.2.1)
Otros consejos
I had a similar problem and this scale worked for me like a charm:
breaks = 10**(1:10)
scale_y_log10(breaks = breaks, labels = comma(breaks))
as you want the intermediate levels, too (10^3.5), you need to tweak the formatting:
breaks = 10**(1:10 * 0.5)
m <- ggplot(diamonds, aes(y = price, x = color)) + geom_boxplot()
m + scale_y_log10(breaks = breaks, labels = comma(breaks, digits = 1))
After executing::
Another solution using scale_y_log10
with trans_breaks
, trans_format
and annotation_logticks()
library(ggplot2)
m <- ggplot(diamonds, aes(y = price, x = color))
m + geom_boxplot() +
scale_y_log10(
breaks = scales::trans_breaks("log10", function(x) 10^x),
labels = scales::trans_format("log10", scales::math_format(10^.x))
) +
theme_bw() +
annotation_logticks(sides = 'lr') +
theme(panel.grid.minor = element_blank())
I think I got it at last by doing some manual transformations with the data before visualization:
d <- diamonds
# computing logarithm of prices
d$price <- log10(d$price)
And work out a formatter to later compute 'back' the logarithmic data:
formatBack <- function(x) 10^x
# or with special formatter (here: "dollar")
formatBack <- function(x) paste(round(10^x, 2), "$", sep=' ')
And draw the plot with given formatter:
m <- ggplot(d, aes(y = price, x = color))
m + geom_boxplot() + scale_y_continuous(formatter='formatBack')
Sorry to the community to bother you with a question I could have solved before! The funny part is: I was working hard to make this plot work a month ago but did not succeed. After asking here, I got it.
Anyway, thanks to @DWin for motivation!