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.