Necesito trazar un gráfico de barras que muestre los recuentos y un gráfico de líneas que muestre la tasa, todo en un gráfico, puedo hacer ambos por separado, pero cuando los combino, la escala de la primera capa (es decir, la geom_bar
) se superpone con la segunda capa (es decir, la geom_line
).
¿Puedo mover el eje de geom_line
a la derecha?
ggplot2
implementación nativa dentroscale_y_*
, actualmente llamadasec.axis
.Respuestas:
A veces un cliente quiere dos escalas y. Darles el discurso "imperfecto" a menudo no tiene sentido. Pero me gusta la insistencia de ggplot2 en hacer las cosas de la manera correcta. Estoy seguro de que ggplot está educando al usuario promedio sobre las técnicas de visualización adecuadas.
¿Quizás pueda usar facetas y escalas gratis para comparar las dos series de datos? - por ejemplo, mira aquí: https://github.com/hadley/ggplot2/wiki/Align-two-plots-on-a-page
fuente
No es posible en ggplot2 porque creo que las gráficas con escalas y separadas (no escalas y que son transformaciones entre sí) son fundamentalmente defectuosas. Algunos problemas:
No son invertibles: dado un punto en el espacio de la trama, no puede asignarlo de forma única a un punto en el espacio de datos.
Son relativamente difíciles de leer correctamente en comparación con otras opciones. Para más detalles, consulte un estudio sobre gráficos de datos a doble escala de Petra Isenberg, Anastasia Bezerianos, Pierre Dragicevic y Jean-Daniel Fekete.
Se manipulan fácilmente para inducir a error: no hay una forma única de especificar las escalas relativas de los ejes, dejándolos abiertos a la manipulación. Dos ejemplos del blog Junkcharts: uno , dos
Son arbitrarios: ¿por qué tener solo 2 escalas, no 3, 4 o diez?
También es posible que desee leer la larga discusión de Stephen Few sobre el tema Ejes de doble escala en los gráficos ¿Son siempre la mejor solución? .
fuente
Comenzando con ggplot2 2.2.0, puede agregar un eje secundario como este (tomado del anuncio de ggplot2 2.2.0 ):
fuente
Tomando las respuestas anteriores y algunos ajustes (y para lo que sea que valga), esta es una forma de lograr dos escalas a través de
sec_axis
:Supongamos un conjunto de datos simple (y puramente ficticio)
dt
: durante cinco días, rastrea el número de interrupciones VS productividad:(los rangos de ambas columnas difieren en aproximadamente el factor 5).
El siguiente código dibujará ambas series que usan en todo el eje y:
Aquí está el resultado (código anterior + algunos ajustes de color):
El punto (aparte de usar
sec_axis
cuando se especifica la escala y_ es multiplicar cada valor de la segunda serie de datos con 5 cuando se especifica la serie. Para obtener las etiquetas correctas en la definición de eje_segundo, entonces necesita dividirse por 5 (y formatear). Entonces Una parte crucial en el código anterior está realmente*5
en geom_line y~./5
en sec_axis (una fórmula que divide el valor actual.
por 5).En comparación (no quiero juzgar los enfoques aquí), así es como se ven dos gráficos uno encima del otro:
Puedes juzgar por ti mismo cuál transporta mejor el mensaje ("¡No interrumpas a las personas en el trabajo!"). Supongo que es una forma justa de decidir.
El código completo para ambas imágenes (no es realmente más de lo que está arriba, solo completo y listo para ejecutarse) está aquí: https://gist.github.com/sebastianrothbucher/de847063f32fdff02c83b75f59c36a7d una explicación más detallada aquí: https: // sebastianrothbucher. github.io/datascience/r/visualization/ggplot/2018/03/24/two-scales-ggplot-r.html
fuente
Hay casos de uso comunes de duelos y ejes, por ejemplo, el climatógrafo que muestra la temperatura mensual y la precipitación. Aquí hay una solución simple, generalizada de la solución de Megatron al permitirle establecer el límite inferior de las variables en algo más que cero:
Datos de ejemplo:
Establezca los siguientes dos valores en valores cercanos a los límites de los datos (puede jugar con estos para ajustar las posiciones de los gráficos; los ejes seguirán siendo correctos):
A continuación se realizan los cálculos necesarios en función de estos límites, y se realiza la trama en sí:
Si desea asegurarse de que la línea roja corresponde al eje y derecho, puede agregar una
theme
oración al código:que colorea el eje de la derecha:
fuente
ylim.prim
yylim.sec
.Puede crear un factor de escala que se aplica a la segunda geoma y al eje y derecho. Esto se deriva de la solución de Sebastián.
Nota: usando
ggplot2
v3.0.0fuente
La columna vertebral técnica para la solución de este desafío fue provista por Kohske hace unos 3 años [ KOHSKE ]. El tema y los tecnicismos en torno a su solución se han discutido en varios casos aquí en Stackoverflow [ID: 18989001, 29235405, 21026598]. Por lo tanto, solo proporcionaré una variación específica y un tutorial explicativo, utilizando las soluciones anteriores.
Supongamos que tenemos algunos datos y1 en el grupo G1 con los cuales algunos datos y2 en el grupo G2 están relacionados de alguna manera, por ejemplo, rango / escala transformados o con algo de ruido agregado. Entonces, uno quiere trazar los datos juntos en un diagrama con la escala de y1 a la izquierda y y2 a la derecha.
Si ahora trazamos nuestros datos junto con algo como
no se alinea bien ya que la escala más pequeña y1 obviamente se colapsa por la escala más grande y2 .
El truco aquí para enfrentar el desafío es trazar técnicamente ambos conjuntos de datos contra la primera escala y1, pero informar el segundo contra un eje secundario con etiquetas que muestren la escala original y2 .
Por lo tanto, creamos una primera función auxiliar CalcFudgeAxis que calcula y recopila características del nuevo eje que se mostrará. La función se puede modificar a gusto de ayones (este solo asigna y2 en el rango de y1 ).
lo que produce algo:
Ahora envolví la solución de Kohske en la segunda función auxiliar PlotWithFudgeAxis (en la que arrojamos el objeto ggplot y el objeto auxiliar del nuevo eje):
Ahora todo se puede juntar: a continuación se muestra el código, cómo se podría usar la solución propuesta en un entorno cotidiano . La llamada de trazado ahora ya no representa los datos originales y2 sino una versión clonada yf (contenida dentro del objeto auxiliar precalculado FudgeAxis ), que se ejecuta en la escala de y1 . El objeto ggplot original se manipula con la función de ayuda de Kohske PlotWithFudgeAxis para agregar un segundo eje preservando las escalas de y2 . Traza también la trama manipulada.
Esto ahora traza como se desee con dos ejes, y1 a la izquierda e y2 a la derecha
La solución anterior es, para aclararlo, un truco inestable limitado. A medida que juega con el núcleo ggplot, arrojará algunas advertencias de que intercambiamos escalas posteriores a los hechos, etc. Debe manejarse con cuidado y puede producir un comportamiento no deseado en otro entorno. Además, es posible que tenga que jugar con las funciones de ayuda para obtener el diseño que desee. La ubicación de la leyenda es un problema (se colocaría entre el panel y el nuevo eje; es por eso que lo descarté). La escala / alineación del eje 2 también es un poco desafiante: el código anterior funciona bien cuando ambas escalas contienen el "0", de lo contrario, un eje se desplaza. Definitivamente con algunas oportunidades para mejorar ...
En caso de que desee guardar la imagen, uno tiene que ajustar la llamada en abrir / cerrar dispositivo:
fuente
El siguiente artículo me ayudó a combinar dos gráficos generados por ggplot2 en una sola fila:
Múltiples gráficos en una página (ggplot2) por Cookbook para R
Y así es como se verá el código en este caso:
fuente
multiplot
stackoverflow.com/a/51220506Para mí, la parte difícil fue descubrir la función de transformación entre los dos ejes. Solía myCurveFit para eso.
Encontrar la función de transformación
función de transformación:
f(y1) = 0.025*x + 2.75
función de transformación:
f(y1) = 40*x - 110
Graficado
Observe cómo se usan las funciones de transformación en la
ggplot
llamada para transformar los datos "sobre la marcha"La primera
stat_summary
llamada es la que establece la base para el primer eje y. La segundastat_summary
llamada se llama para transformar los datos. Recuerde que todos los datos tomarán como base el primer eje y. De modo que los datos deben normalizarse para el primer eje y. Para hacer eso, uso la función de transformación en los datos:y=packetOkSinr*40 - 110
Ahora, para transformar el segundo eje utilizo la función opuesta dentro de la
scale_y_continuous
llamada:sec.axis=sec_axis(~.*0.025+2.75, name="y_second")
.fuente
coef(lm(c(-70, -110) ~ c(1,0)))
ycoef(lm(c(1,0) ~ c(-70, -110)))
. Podría definir una función auxiliar comoequationise <- function(range = c(-70, -110), target = c(1,0)){ c = coef(lm(target ~ range)) as.formula(substitute(~ a*. + b, list(a=c[[2]], b=c[[1]]))) }
Definitivamente podríamos construir una parcela con doble Y. axises utilizando la base R funtion
plot
.fuente
Puede usar
facet_wrap(~ variable, ncol= )
una variable para crear una nueva comparación. No está en el mismo eje, pero es similar.fuente
Reconozco y estoy de acuerdo con Hadley (y otros), que las escalas y separadas son "fundamentalmente defectuosas". Dicho esto, a menudo desearía
ggplot2
tener la función, particularmente cuando los datos están en formato ancho y rápidamente quiero visualizar o verificar los datos (es decir, solo para uso personal).Si bien la
tidyverse
biblioteca hace que sea bastante fácil convertir los datos a formato largo (de modo quefacet_grid()
funcione), el proceso aún no es trivial, como se ve a continuación:fuente
sec_axis
.La respuesta de Hadley da una referencia interesante al informe de Stephen Few Ejes de doble escala en gráficos ¿Son siempre la mejor solución? .
No sé qué significa el OP con "recuentos" y "tasa", pero una búsqueda rápida me da recuentos y tasas , por lo que obtengo algunos datos sobre accidentes en el alpinismo norteamericano 1 :
Y luego traté de hacer el gráfico como Pocos sugirió en la página 7 del informe mencionado anteriormente (y siguiendo la solicitud de OP para graficar los recuentos como un gráfico de barras y las tasas como un gráfico de líneas):
Y este es el resultado:
Pero no me gusta mucho y no puedo ponerle una leyenda fácilmente ...
1 WILLIAMSON, Jed, y col. Accidentes en el alpinismo norteamericano 2005. The Mountaineers Books, 2005.
fuente
Aparentemente parece ser una pregunta simple, pero se aturde alrededor de 2 preguntas fundamentales. A) Cómo lidiar con datos multiescalares mientras se presenta en un cuadro comparativo, y en segundo lugar, B) si esto se puede hacer sin algunas prácticas de regla de pulgar de la programación R como i) fusión de datos, ii) facetado, iii) agregar otra capa a la existente. La solución que se proporciona a continuación satisface las dos condiciones anteriores, ya que trata los datos sin tener que reescalarlos y, en segundo lugar, no se utilizan las técnicas mencionadas.
Aquí está el resultado,
Para aquellos interesados en saber más sobre este método, siga el siguiente enlace. Cómo trazar un gráfico de eje 2 y con barras una al lado de la otra sin volver a escalar los datos
fuente
Encontré que esta respuesta me ayudó más, pero descubrí que había algunos casos extremos que no parecían manejarse correctamente, en particular los casos negativos, y también el caso donde mis límites tenían 0 distancia (lo que puede suceder si estamos agarrando nuestros límites de max / min de datos). Las pruebas parecen indicar que esto funciona consistentemente
Yo uso el siguiente código. Aquí supongo que tenemos [x1, x2] que queremos transformar a [y1, y2]. La forma en que manejé esto fue transformar [x1, x2] a [0,1] (una transformación lo suficientemente simple), luego [0,1] a [y1, y2].
Las partes clave aquí son que transformamos el eje y secundario con
~((.-ylim.prim[1]) *b + ylim.sec[1])
y luego aplicamos el inverso a los valores realesy = ylim.prim[1]+(Temp-ylim.sec[1])/b)
. También debemos asegurarnos de esolimits = ylim.prim
.fuente