Cómo mostrar solo valores enteros en un eje usando ggplot2


87

Tengo la siguiente trama:

library(reshape)
library(ggplot2)
library(gridExtra)
require(ggplot2)



data2<-structure(list(IR = structure(c(4L, 3L, 2L, 1L, 4L, 3L, 2L, 1L
), .Label = c("0.13-0.16", "0.17-0.23", "0.24-0.27", "0.28-1"
), class = "factor"), variable = structure(c(1L, 1L, 1L, 1L, 
2L, 2L, 2L, 2L), .Label = c("Real queens", "Simulated individuals"
), class = "factor"), value = c(15L, 11L, 29L, 42L, 0L, 5L, 21L, 
22L), Legend = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), .Label = c("Real queens", 
"Simulated individuals"), class = "factor")), .Names = c("IR", 
"variable", "value", "Legend"), row.names = c(NA, -8L), class = "data.frame")
p <- ggplot(data2, aes(x =factor(IR), y = value, fill = Legend, width=.15))


data3<-structure(list(IR = structure(c(4L, 3L, 2L, 1L, 4L, 3L, 2L, 1L
), .Label = c("0.13-0.16", "0.17-0.23", "0.24-0.27", "0.28-1"
), class = "factor"), variable = structure(c(1L, 1L, 1L, 1L, 
2L, 2L, 2L, 2L), .Label = c("Real queens", "Simulated individuals"
), class = "factor"), value = c(2L, 2L, 6L, 10L, 0L, 1L, 4L, 
4L), Legend = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), .Label = c("Real queens", 
"Simulated individuals"), class = "factor")), .Names = c("IR", 
"variable", "value", "Legend"), row.names = c(NA, -8L), class = "data.frame")
q<- ggplot(data3, aes(x =factor(IR), y = value, fill = Legend, width=.15))


##the plot##
q + geom_bar(position='dodge', colour='black') + ylab('Frequency') + xlab('IR')+scale_fill_grey() +theme(axis.text.x=element_text(colour="black"), axis.text.y=element_text(colour="Black"))+ opts(title='', panel.grid.major = theme_blank(),panel.grid.minor = theme_blank(),panel.border = theme_blank(),panel.background = theme_blank(), axis.ticks.x = theme_blank())

Quiero que el eje y muestre solo números enteros. Si esto se logra mediante redondeo o mediante un método más elegante, no es realmente importante para mí.


2
¿Ha mirado alguna de las funciones de escala? scale_y_continuous¿tal vez?
joran

Leí algunas respuestas a preguntas similares y tenía la impresión de que scale_y_continuous se convertía de otros formatos numéricos (por ejemplo, notación científica), pero no acomodaba la conversión de número real a entero que estaba buscando. Podría estar equivocado ...
Atticus29

Respuestas:


41

Con un scale_y_continuous()argumento y breaks=puede establecer los puntos de ruptura para el eje y en los números enteros que desea mostrar.

ggplot(data2, aes(x =factor(IR), y = value, fill = Legend, width=.15)) +
    geom_bar(position='dodge', colour='black')+
    scale_y_continuous(breaks=c(1,3,7,10))

41
Esta solución solo es buena para situaciones en las que sabe qué valores están en los ejes. No es una buena solución general.
swolf

3
Nota para la posteridad: geom_barya no funciona con y estética (reemplazar con geom_col). Y, aunque no es una solución general, en este ejemplo, llamar a pretty con una n específica puede solucionar el problema original (y es más flexible que las interrupciones de codificación): q + geom_col(position='dodge', colour='black') + xlab('IR')+scale_fill_grey() + theme_bw() + scale_y_continuous('Frequency', breaks=function(x) pretty(x, n=6))
helmingstay

72

Si tiene el scalespaquete, puede usarlo pretty_breaks()sin tener que especificar manualmente los descansos.

q + geom_bar(position='dodge', colour='black') + 
scale_y_continuous(breaks= pretty_breaks())

17
Esto parecía hacer casi lo que hace el método predeterminado y todavía tenía puntos decimales en los descansos.
kory

De donde pretty_breaks()viene
Marian


12
pretty_breaks()son bonitos, pero no siempre enteros. Obviamente, hay belleza en los decimales ...
PatrickT

50

Esto es lo que uso:

ggplot(data3, aes(x = factor(IR), y = value, fill = Legend, width = .15)) +
  geom_col(position = 'dodge', colour = 'black') + 
  scale_y_continuous(breaks = function(x) unique(floor(pretty(seq(0, (max(x) + 1) * 1.1)))))

17

Puede utilizar una etiquetadora personalizada. Por ejemplo, esta función garantiza que solo se produzcan rupturas de enteros:

int_breaks <- function(x, n = 5) {
  l <- pretty(x, n)
  l[abs(l %% 1) < .Machine$double.eps ^ 0.5] 
}

Usar como

+ scale_y_continuous(breaks = int_breaks)

Funciona tomando los descansos predeterminados y solo conservando aquellos que son números enteros. Si muestra muy pocas interrupciones para sus datos, aumente n, por ejemplo:

+ scale_y_continuous(breaks = function(x) int_breaks(x, n = 10))

Este hace que pierda el entero 1 si solo tiene datos de 0 a 1,25 o lo que sea. Solo veo 0 en el eje x.
kory

1
Me gusta esto por simplicidad. Tenga en cuenta que npodría necesitar algunos ajustes dependiendo de su rango de valores. parece determinar cuántos descansos habrá (aproximadamente).
Marian

13

Estas soluciones no funcionaron para mí y no explicaron las soluciones.

El breaksargumento de las scale_*_continuousfunciones se puede usar con una función personalizada que toma los límites como entrada y devuelve cortes como salida. De forma predeterminada, los límites del eje se ampliarán un 5% en cada lado para datos continuos (en relación con el rango de datos). Es probable que los límites del eje no sean valores enteros debido a esta expansión.

La solución que estaba buscando era simplemente redondear el límite inferior al número entero más cercano, redondear el límite superior al número entero más cercano y luego tener rupturas en los valores enteros entre estos puntos finales. Por lo tanto, utilicé la función de pausas:

brk <- function(x) seq(ceiling(x[1]), floor(x[2]), by = 1)

El fragmento de código requerido es:

scale_y_continuous(breaks = function(x) seq(ceiling(x[1]), floor(x[2]), by = 1))

El ejemplo reproducible de la pregunta original es:

data3 <-
  structure(
    list(
      IR = structure(
        c(4L, 3L, 2L, 1L, 4L, 3L, 2L, 1L),
        .Label = c("0.13-0.16", "0.17-0.23", "0.24-0.27", "0.28-1"),
        class = "factor"
      ),
      variable = structure(
        c(1L, 1L, 1L, 1L,
          2L, 2L, 2L, 2L),
        .Label = c("Real queens", "Simulated individuals"),
        class = "factor"
      ),
      value = c(2L, 2L, 6L, 10L, 0L, 1L, 4L,
                4L),
      Legend = structure(
        c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L),
        .Label = c("Real queens",
                   "Simulated individuals"),
        class = "factor"
      )
    ),
    row.names = c(NA,-8L),
    class = "data.frame"
  )

ggplot(data3, aes(
  x = factor(IR),
  y = value,
  fill = Legend,
  width = .15
)) +
  geom_col(position = 'dodge', colour = 'black') + ylab('Frequency') + xlab('IR') +
  scale_fill_grey() +
  scale_y_continuous(
    breaks = function(x) seq(ceiling(x[1]), floor(x[2]), by = 1),
    expand = expand_scale(mult = c(0, 0.05))
    ) +
  theme(axis.text.x=element_text(colour="black", angle = 45, hjust = 1), 
        axis.text.y=element_text(colour="Black"),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.border = element_blank(),
        panel.background = element_blank(), 
        axis.ticks.x = element_blank())

2
La mejor respuesta aquí
Martin

3

Google me trajo a esta pregunta. Estoy tratando de usar números reales en escala ay. Los números de la escala y están en millones.

El método del paquete de escalascomma introduce una coma en mis números grandes. Esta publicación sobre R-Bloggers explica un enfoque simple usando el commamétodo:

library(scales)

big_numbers <- data.frame(x = 1:5, y = c(1000000:1000004))

big_numbers_plot <- ggplot(big_numbers, aes(x = x, y = y))+
geom_point()

big_numbers_plot + scale_y_continuous(labels = comma)

Disfruta R :)


1
Las otras soluciones aquí en realidad no funcionaron para mí, o parecían ridículamente complicadas. Este funcionó y fue fácil de hacer.
Brian Doherty

gracias @BrianDoherty, la simplicidad es la clave para la mayoría de las cosas ...
Tony Cronin

3

Todas las respuestas existentes parecen requerir funciones personalizadas o fallan en algunos casos.

Esta línea hace rupturas enteras:

bad_scale_plot +
  scale_y_continuous(breaks = scales::breaks_extended(Q = c(1, 5, 2, 4, 3)))

Para obtener más información, consulte la documentación ?labeling::extended(que es una función llamada por scales::breaks_extended).

Básicamente, el argumento Qes un conjunto de números agradables que el algoritmo intenta utilizar para los saltos de escala. La trama original produce roturas no enteros (0, 2,5, 5, y 7,5) debido a que el valor predeterminado para Qincluye 2,5: Q = c(1,5,2,2.5,4,3).

EDITAR: como se señaló en un comentario, las rupturas no enteras pueden ocurrir cuando el eje y tiene un rango pequeño. De forma predeterminada, breaks_extended()intenta realizar n = 5rupturas, lo que es imposible cuando el rango es demasiado pequeño. Las pruebas rápidas muestran que los rangos más anchos que 0 <y <2.5 dan saltos enteros ( ntambién se pueden reducir manualmente).


1

Esta respuesta se basa en la respuesta de @ Axeman para abordar el comentario de kory de que si los datos solo van de 0 a 1, no se muestra ninguna ruptura en 1. Esto parece deberse a una inexactitud en las prettysalidas que parecen ser 1 y no son idénticas a 1 (ver ejemplo al final).

Por lo tanto, si usa

int_breaks_rounded <- function(x, n = 5)  pretty(x, n)[round(pretty(x, n),1) %% 1 == 0]

con

+ scale_y_continuous(breaks = int_breaks_rounded)

tanto 0 como 1 se muestran como pausas.

Ejemplo para ilustrar la diferencia con Axeman

testdata <- data.frame(x = 1:5, y = c(0,1,0,1,1))

p1 <- ggplot(testdata, aes(x = x, y = y))+
  geom_point()


p1 + scale_y_continuous(breaks = int_breaks)
p1 + scale_y_continuous(breaks =  int_breaks_rounded)

Ambos trabajarán con los datos proporcionados en la pregunta inicial.

Ilustración de por qué se requiere redondeo

pretty(c(0,1.05),5)
#> [1] 0.0 0.2 0.4 0.6 0.8 1.0 1.2
identical(pretty(c(0,1.05),5)[6],1)
#> [1] FALSE

1

Encontré esta solución de Joshua Cook y funcionó bastante bien.

integer_breaks <- function(n = 5, ...) {
fxn <- function(x) {
breaks <- floor(pretty(x, n, ...))
names(breaks) <- attr(breaks, "labels")
breaks
}
return(fxn)
}

q + geom_bar(position='dodge', colour='black') + 
scale_y_continuous(breaks = integer_breaks())

La fuente es: https://joshuacook.netlify.app/post/integer-values-ggplot-axis/

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.