Como exibir apenas valores inteiros em um eixo usando ggplot2


87

Eu tenho o seguinte enredo:

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())

Eu quero que o eixo y exiba apenas números inteiros. Se isso é feito por arredondamento ou por um método mais elegante, não é muito importante para mim.


2
Você já olhou para alguma das funções da escala? scale_y_continuoustalvez?
— joran,

Eu li algumas respostas para perguntas semelhantes e tive a impressão de que scale_y_continuous converteu de outros formatos numéricos (por exemplo, notação científica), mas não acomodou o número real para a conversão de inteiro que eu estava procurando. Posso estar enganado ...
— Atticus

Respostas:


41

Com o scale_y_continuous()argumento e, breaks=você pode definir os pontos de quebra do eixo y para inteiros que deseja exibir.

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 solução só é boa para situações em que você sabe quais valores estão nos eixos. Não é uma boa solução geral.
— swolf de

3
Nota para a posteridade: geom_barnão funciona mais com estética y (substitua por geom_col). E, embora não seja uma solução geral, neste exemplo, chamar bonito com um n específico pode corrigir o problema original (e é mais flexível do que as quebras de codificação): 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

Se você tiver o scalespacote, poderá usá-lo pretty_breaks()sem precisar especificar manualmente as quebras.

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

17
Isso parecia fazer quase o que o método padrão faz e eu ainda tinha casas decimais nas quebras.
— kory

De onde pretty_breaks()vem?
— Marian


12
pretty_breaks()são bonitos, mas nem sempre inteiros. Obviamente, há beleza em decimais ...
— PatrickT

50

Isso é o que eu 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

Você pode usar uma etiquetadora personalizada. Por exemplo, esta função garante produzir apenas quebras de inteiros:

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

Use como

+ scale_y_continuous(breaks = int_breaks)

Ele funciona pegando as pausas padrão e mantendo apenas aquelas que são inteiras. Se estiver mostrando poucas quebras para seus dados, aumente n, por exemplo:

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

Este faz com que você perca o inteiro 1 se você tiver dados apenas de 0 a 1,25 ou o que quer que seja. Vejo apenas 0 no eixo x.
— kory

1
Eu gosto disso por causa da simplicidade. Observe que npode ser necessário alguns ajustes, dependendo da sua faixa de valores. parece determinar quantas quebras haverá (aproximadamente).
— Marian

13

Essas soluções não funcionaram para mim e não explicaram as soluções.

O breaksargumento para as scale_*_continuousfunções pode ser usado com uma função personalizada que leva os limites como entrada e retorna quebras como saída. Por padrão, os limites do eixo serão expandidos em 5% em cada lado para dados contínuos (em relação ao intervalo de dados). Os limites do eixo provavelmente não serão valores inteiros devido a essa expansão.

A solução que eu estava procurando era simplesmente arredondar o limite inferior para o inteiro mais próximo, arredondar o limite superior para o inteiro mais próximo e, em seguida, ter quebras nos valores inteiros entre esses pontos finais. Portanto, usei a função de interrupções:

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

O snippet de código necessário é:

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

O exemplo reproduzível da pergunta original é:

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
Melhor resposta aqui
— Martin

3

O Google me trouxe a esta questão. Estou tentando usar números reais em escala y. Os números da escala y estão em milhões.

O método do pacote de escalascomma introduz uma vírgula para meus números grandes. Esta postagem no R-Bloggers explica uma abordagem simples usando o 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)

Aproveite R :)


1
As outras soluções aqui não funcionaram para mim ou pareciam ridiculamente complicadas. Este funcionou e foi simples de fazer.
— Brian Doherty

obrigado @BrianDoherty, simplicidade é a chave para a maioria das coisas ...
— Tony Cronin

3

Todas as respostas existentes parecem exigir funções personalizadas ou falham em alguns casos.

Esta linha faz quebras inteiras:

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

Para obter mais informações, consulte a documentação ?labeling::extended(que é uma função chamada por scales::breaks_extended).

Basicamente, o argumento Qé um conjunto de números legais que o algoritmo tenta usar para quebras de escala. A parcela inicial produz intervalos não inteiros (0, 2,5, 5 e 7,5), porque o valor predefinido para Qinclui 2,5: Q = c(1,5,2,2.5,4,3).

EDITAR: como apontado em um comentário, quebras não inteiras podem ocorrer quando o eixo y tem um pequeno intervalo. Por padrão, breaks_extended()tenta fazer n = 5pausas, o que é impossível quando o alcance é muito pequeno. O teste rápido mostra que intervalos maiores que 0 <y <2,5 dão quebras de inteiros ( ntambém podem ser diminuídos manualmente).


1

Esta resposta baseia-se na resposta de @Axeman para abordar o comentário de kory de que se os dados vão apenas de 0 a 1, nenhuma quebra é mostrada em 1. Isso parece ser devido à imprecisão nas prettysaídas que parecem ser 1 não sendo idênticas a 1 (veja o exemplo no final).

Portanto, se você usar

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

com

+ scale_y_continuous(breaks = int_breaks_rounded)

ambos 0 e 1 são mostrados como quebras.

Exemplo para ilustrar a diferença do 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 trabalharão com os dados fornecidos na pergunta inicial.

Ilustração de por que o arredondamento é necessário

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

Encontrei essa solução com Joshua Cook e funcionou muito bem.

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())

A fonte é: https://joshuacook.netlify.app/post/integer-values-ggplot-axis/

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.