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.