Jak wyświetlić tylko wartości całkowite na osi przy użyciu ggplot2

87

Mam następującą fabułę:

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

Chcę, aby oś Y wyświetlała tylko liczby całkowite. Nie jest dla mnie ważne, czy odbywa się to poprzez zaokrąglanie, czy za pomocą bardziej eleganckiej metody.

Atticus29
źródło
2
Czy spojrzałeś w ogóle na którąś z funkcji skali? scale_y_continuousmoże?
joran
Przeczytałem kilka odpowiedzi na podobne pytania i miałem wrażenie, że scale_y_continuous przekonwertowane z innych formatów liczbowych (np. Notacji naukowej), ale nie uwzględniłem konwersji liczby rzeczywistej na liczbę całkowitą, której szukałem. Mogę się mylić ...
Atticus

Odpowiedzi:

41

Za pomocą scale_y_continuous()argumentów i breaks=możesz ustawić punkty przerwania osi y na liczby całkowite, które chcesz wyświetlić.

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))
Didzis Elferts
źródło
41
To rozwiązanie jest dobre tylko w sytuacjach, w których wiesz, jakie wartości znajdują się na osiach. Nie jest to dobre rozwiązanie ogólne.
swolf
3
Uwaga dla potomnych: geom_barnie działa już z estetyką y (zamień na geom_col). I chociaż nie jest to ogólne rozwiązanie, w tym przykładzie wywołanie pretty z określonym n może naprawić oryginalny problem (i jest bardziej elastyczne niż przerwy w twardym kodowaniu): 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

Jeśli masz scalespakiet, możesz go używać pretty_breaks()bez konieczności ręcznego określania przerw.

q + geom_bar(position='dodge', colour='black') + 
scale_y_continuous(breaks= pretty_breaks())
Sealander
źródło
17
Wydawało się, że robi to prawie to, co robi metoda domyślna, a nadal miałem kropki dziesiętne w przerwach.
kory
Skąd się pretty_breaks()bierze?
Marian
12
pretty_breaks()są ładne, ale nie zawsze są liczbami całkowitymi. Oczywiście jest piękno w
ułamkach
50

Oto czego używam:

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)))))
Daniel Gardiner
źródło
18

Możesz użyć niestandardowej etykieciarki. Na przykład ta funkcja gwarantuje tworzenie tylko podziałów całkowitych:

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

Użyj jako

+ scale_y_continuous(breaks = int_breaks)

Działa, biorąc domyślne przerwy i zachowując tylko te, które są liczbami całkowitymi. Jeśli pokazuje zbyt mało przerw dla danych, zwiększ n, np .:

+ scale_y_continuous(breaks = function(x) int_breaks(x, n = 10))
Axeman
źródło
To powoduje, że tracisz liczbę całkowitą 1, jeśli masz dane tylko od 0 do 1,25 lub co masz. Na osi X widzę tylko 0.
kory
1
Podoba mi się to ze względu na prostotę. Zauważ, że nmoże to wymagać pewnych ulepszeń w zależności od zakresu wartości. wydaje się, że określa, ile będzie przerw (w przybliżeniu).
Marian
13

Te rozwiązania nie zadziałały i nie wyjaśniły rozwiązań.

breaksArgument scale_*_continuousfunkcji może być używany z funkcji niestandardowej, która zabierze granice jako dane wejściowe i zwraca przerw jako wyjście. Domyślnie granice osi zostaną rozszerzone o 5% z każdej strony dla danych ciągłych (w stosunku do zakresu danych). Z powodu tego rozszerzenia granice osi prawdopodobnie nie będą wartościami całkowitymi.

Rozwiązaniem, którego szukałem, było po prostu zaokrąglić dolną granicę w górę do najbliższej liczby całkowitej, zaokrąglić górną granicę w dół do najbliższej liczby całkowitej, a następnie zrobić przerwy na wartościach całkowitych między tymi punktami końcowymi. Dlatego użyłem funkcji breaks:

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

Wymagany fragment kodu to:

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

Odtwarzalny przykład z oryginalnego pytania to:

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())
Nat
źródło
2
Najlepsza odpowiedź tutaj
Martin
3

Google doprowadziło mnie do tego pytania. Próbuję użyć liczb rzeczywistych w dowolnej skali. Liczby w skali y są podane w milionach.

Metoda pakietu wagcomma wprowadza przecinek do moich dużych liczb. Ten post na R-Bloggers wyjaśnia proste podejście przy użyciu commametody:

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)

Ciesz się R :)

Tony Cronin
źródło
1
Inne rozwiązania tutaj tak naprawdę nie działały dla mnie lub wydawały się absurdalnie skomplikowane. Ten działał i był prosty do wykonania.
Brian Doherty
dzięki @BrianDoherty, prostota jest kluczem do większości rzeczy ...
Tony Cronin
3

Wydaje się, że wszystkie istniejące odpowiedzi wymagają niestandardowych funkcji lub w niektórych przypadkach zawodzą.

W tym wierszu podział liczb całkowitych:

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

Aby uzyskać więcej informacji, zobacz dokumentację ?labeling::extended(która jest funkcją wywoływaną przez scales::breaks_extended).

Zasadniczo argumentem Qjest zbiór ładnych liczb, których algorytm próbuje użyć do przerwania skali. Oryginalny wykres powoduje przerwy niż całkowite (0, 2,5, 5, 7,5), ponieważ wartość domyślna Qzawiera 2,5: Q = c(1,5,2,2.5,4,3).

EDYCJA: jak wskazano w komentarzu, przerwy niecałkowite mogą wystąpić, gdy oś Y ma mały zakres. Domyślnie breaks_extended()próbuje robić n = 5przerwy, co jest niemożliwe przy zbyt małym zakresie. Szybkie testy pokazują, że zakresy szersze niż 0 <y <2,5 dają przerwy w liczbach całkowitych ( nmożna je również zmniejszyć ręcznie).

Nacięcie
źródło
1

Ta odpowiedź opiera się na odpowiedzi @ Axeman, która odnosi się do komentarza kory, który mówi, że jeśli dane idą tylko od 0 do 1, nie ma przerwy na 1. Wydaje się, że jest to spowodowane niedokładnością w prettywynikach, które wydają się być 1, które nie są identyczne z 1 (patrz przykład na końcu).

Dlatego jeśli używasz

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

z

+ scale_y_continuous(breaks = int_breaks_rounded)

zarówno 0, jak i 1 są wyświetlane jako przerwy.

Przykład ilustrujący różnicę w stosunku do Axemana

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)

Oba będą działać z danymi podanymi w pierwszym pytaniu.

Ilustracja przedstawiająca, dlaczego zaokrąglanie jest wymagane

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
Sarah
źródło
1

Znalazłem to rozwiązanie od Joshua Cooka i działało całkiem nieźle.

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

Źródłem jest: https://joshuacook.netlify.app/post/integer-values-ggplot-axis/

Bruno Vidigal
źródło