Etiquetas de eje giratorio y espaciado en ggplot2

671

Tengo un diagrama donde el eje x es un factor cuyas etiquetas son largas. Aunque probablemente no sea una visualización ideal, por ahora me gustaría simplemente rotar estas etiquetas para que sean verticales. He descubierto esta parte con el código a continuación, pero como puede ver, las etiquetas no son totalmente visibles.

data(diamonds)
diamonds$cut <- paste("Super Dee-Duper",as.character(diamonds$cut))
q <- qplot(cut,carat,data=diamonds,geom="boxplot")
q + opts(axis.text.x=theme_text(angle=-90))

ingrese la descripción de la imagen aquí

Christopher DuBois
fuente

Respuestas:

1114

Cambia la última línea a

q + theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))

Por defecto, los ejes están alineados en el centro del texto, incluso cuando se giran. Cuando gira +/- 90 grados, generalmente desea que se alinee en el borde:

texto alternativo

La imagen de arriba es de esta publicación de blog .

Jonathan Chang
fuente
95
En la versión más reciente de ggplot2, el comando sería: q + theme(axis.text.x=element_text(angle = -90, hjust = 0))
rnorberg
55
Para aquellos para quienes simplemente no se está comportando como se describe aquí, intente theme(axis.text.x=element_text(angle = 90, vjust = 0.5)). A partir de ggplot2 0.9.3.1, esta parece ser la solución.
lilster
42
En realidad, tuve que combinar las dos soluciones anteriores para obtener etiquetas correctamente alineadas:q + theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
jupp0r
32
@ jupp0r es correcto. theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))ES EL QUE FUNCIONA ACTUALMENTE.
51
si quería etiquetas rotativas de 45 ° (más fácil de leer) theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust=1))da buenos resultados
jan-glx
89

Para hacer que el texto en las etiquetas de marca sea totalmente visible y leído en la misma dirección que la etiqueta del eje y, cambie la última línea a

q + theme(axis.text.x=element_text(angle=90, hjust=1))
e3bo
fuente
82

Utilizar coord_flip()

data(diamonds)
diamonds$cut <- paste("Super Dee-Duper",as.character(diamonds$cut))

qplot(cut,carat,data = diamonds, geom = "boxplot") +
  coord_flip()

ingrese la descripción de la imagen aquí


En el capítulo 3.9 de R para Data Science , Wickham y Grolemund hablan de esta pregunta exacta:

coord_flip()cambia los ejes x e y. Esto es útil (por ejemplo), si desea diagramas de caja horizontales. También es útil para etiquetas largas: es difícil hacer que se ajusten sin superponerse en el eje x.

Rico Pauloo
fuente
26

Me gustaría proporcionar una solución alternativa, se requería una solución robusta similar a lo que estoy a punto de proponer en la última versión de ggtern , desde que introduje la función de rotación del lienzo.

Básicamente, debe determinar las posiciones relativas mediante trigonometría, mediante la construcción de una función que devuelva un element_textobjeto, dado el ángulo (es decir, grados) y la información de posicionamiento (es decir, una de x, y, arriba o derecha).

#Load Required Libraries
library(ggplot2)
library(gridExtra)

#Build Function to Return Element Text Object
rotatedAxisElementText = function(angle,position='x'){
  angle     = angle[1]; 
  position  = position[1]
  positions = list(x=0,y=90,top=180,right=270)
  if(!position %in% names(positions))
    stop(sprintf("'position' must be one of [%s]",paste(names(positions),collapse=", ")),call.=FALSE)
  if(!is.numeric(angle))
    stop("'angle' must be numeric",call.=FALSE)
  rads  = (angle - positions[[ position ]])*pi/180
  hjust = 0.5*(1 - sin(rads))
  vjust = 0.5*(1 + cos(rads))
  element_text(angle=angle,vjust=vjust,hjust=hjust)
}

Francamente, en mi opinión, creo que una opción 'automática' debería estar disponible ggplot2para los argumentos hjusty vjust, al especificar el ángulo, de todos modos, demostremos cómo funciona lo anterior.

#Demonstrate Usage for a Variety of Rotations
df    = data.frame(x=0.5,y=0.5)
plots = lapply(seq(0,90,length.out=4),function(a){
  ggplot(df,aes(x,y)) + 
    geom_point() + 
    theme(axis.text.x = rotatedAxisElementText(a,'x'),
          axis.text.y = rotatedAxisElementText(a,'y')) +
    labs(title = sprintf("Rotated %s",a))
})
grid.arrange(grobs=plots)

Lo que produce lo siguiente:

Ejemplo

Nicholas Hamilton
fuente
1
No obtengo los mismos resultados, para mí el texto del eje nunca se ajusta bien usando su método automático. Sin embargo, el uso rads = (-angle - positions[[ position ]])*pi/180produjo mejores ubicaciones. Tenga en cuenta el signo menos adicional antes del ángulo. Gracias por el código de todos modos :)
asac
7

El paquete ggpubr ofrece un acceso directo que hace lo correcto de forma predeterminada (alinear el texto a la derecha, alinear el cuadro de texto del medio para marcar):

library(ggplot2)
diamonds$cut <- paste("Super Dee-Duper", as.character(diamonds$cut))
q <- qplot(cut, carat, data = diamonds, geom = "boxplot")
q + ggpubr::rotate_x_text()

Creado el 06/11/2018 por el paquete reprex (v0.2.1)

Encontrado con una búsqueda de GitHub para los nombres de argumentos relevantes: https://github.com/search?l=R&q=element_text+angle+90+vjust+org%3Acran&type=Code

krlmlr
fuente
6

Alternativamente, ggplot 3.3.0proporciona guide_axis(n.dodge = 2)(como guideargumento scale_..o como xargumento para guides) superar el problema de sobre-trazado esquivando las etiquetas verticalmente. Funciona bastante bien en este caso:

library(ggplot2)
data(diamonds)
diamonds$cut <- paste("Super Dee-Duper",as.character(diamonds$cut))

ggplot(diamonds, aes(cut, carat)) + 
  geom_boxplot() +
  scale_x_discrete(guide = guide_axis(n.dodge = 2)) +
  NULL

jan-glx
fuente
1

Para obtener etiquetas de tick x legibles sin dependencias adicionales, desea utilizar:

  ... +
  theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5)) +
  ...

Esto gira las etiquetas de marca 90 ° en sentido antihorario y las alinea verticalmente en su extremo ( hjust = 1) y sus centros horizontalmente con la marca de marca correspondiente ( vjust = 0.5).

Ejemplo completo:

library(ggplot2)
data(diamonds)
diamonds$cut <- paste("Super Dee-Duper",as.character(diamonds$cut))
q <- qplot(cut,carat,data=diamonds,geom="boxplot")
q + theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5))


Tenga en cuenta que los parámetros vjust/ hjustde justificación vertical / horizontal element_textson relativos al texto. Por lo tanto, vjustes responsable de la horizontal alineación .

Sin vjust = 0.5esto se vería así:

q + theme(axis.text.x = element_text(angle = 90, hjust = 1))

Sin hjust = 1esto se vería así:

q + theme(axis.text.x = element_text(angle = 90, vjust = 0.5))

Si por alguna razón (por cable) desea girar las etiquetas de marca 90 ° en sentido horario (de modo que se puedan leer desde la izquierda), necesitaría usar: q + theme(axis.text.x = element_text(angle = -90, vjust = 0.5, hjust = -1)) .

Todo esto ya se ha discutido en los comentarios de esta respuesta, pero vuelvo a esta pregunta con tanta frecuencia que quiero una respuesta que pueda copiar sin leer los comentarios.

jan-glx
fuente
0

Una alternativa a coord_flip()es usar el ggstancepaquete. La ventaja es que facilita la combinación de los gráficos con otros tipos de gráficos y puede, quizás lo más importante, establecer proporciones de escala fija para su sistema de coordenadas .

library(ggplot2)
library(ggstance)

diamonds$cut <- paste("Super Dee-Duper", as.character(diamonds$cut))

ggplot(data=diamonds, aes(carat, cut)) + geom_boxploth()

Creado el 11-03-2020 por el paquete reprex (v0.3.0)

Tjebo
fuente