Как отображать только целые значения на оси с помощью ggplot2

87

У меня такой сюжет:

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

Я хочу, чтобы по оси Y отображались только целые числа. Для меня не важно, достигается ли это округлением или более элегантным методом.

Аттикус29
источник
2
Вы вообще смотрели на какие-либо функции масштабирования? scale_y_continuousможет быть?
joran
Я прочитал несколько ответов на похожие вопросы, и у меня сложилось впечатление, что scale_y_continuous преобразовано из других числовых форматов (например, научная нотация), но не поддерживает преобразование действительного числа в целое, которое я искал. Я могу ошибаться ...
Atticus29,

Ответы:

41

С помощью scale_y_continuous()аргумента и breaks=вы можете установить точки разрыва для оси Y на целые числа, которые вы хотите отобразить.

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
Это решение подходит только для ситуаций, когда вы знаете, какие значения находятся на осях. Не очень хорошее общее решение.
swolf 08
3
Примечание для потомков: geom_barбольше не работает с y aesthetic (заменить на geom_col). И, хотя это и не является общим решением, в этом примере вызов pretty с конкретным 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

Если у вас есть scalesпакет, вы можете использовать его pretty_breaks()без необходимости вручную указывать перерывы.

q + geom_bar(position='dodge', colour='black') + 
scale_y_continuous(breaks= pretty_breaks())
Морской котик
источник
17
Казалось, что это почти то же самое, что и метод по умолчанию, и у меня все еще были десятичные точки в перерывах.
kory
Откуда pretty_breaks()взялось?
Мариан
12
pretty_breaks()красивы, но не всегда целые. Очевидно, что в десятичных дробях есть красота ...
PatrickT
50

Вот что я использую:

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)))))
Даниэль Гардинер
источник
18

Вы можете использовать специальный этикетировщик. Например, эта функция гарантирует создание только целочисленных разрывов:

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

Использовать как

+ scale_y_continuous(breaks = int_breaks)

Он работает, беря перерывы по умолчанию и сохраняя только целые числа. Если для ваших данных слишком мало пауз, увеличьте n, например:

+ scale_y_continuous(breaks = function(x) int_breaks(x, n = 10))
Топорщик
источник
Это приводит к тому, что вы теряете целое число 1, если у вас есть данные только от 0 до 1,25 или что у вас есть. Я вижу только 0 по оси абсцисс.
kory
1
Мне это нравится для простоты. Обратите внимание, что в nзависимости от диапазона значений может потребоваться некоторая настройка. вроде определяет, сколько будет перерывов (примерно).
Мариан
13

Эти решения не помогли мне и не объяснили решения.

breaksАргумент к scale_*_continuousфункции может быть использован с пользовательской функцией , которая принимает пределы в качестве входных и возвращают брейки , как выход. По умолчанию пределы оси будут расширены на 5% с каждой стороны для непрерывных данных (относительно диапазона данных). Из-за этого расширения пределы оси, скорее всего, не будут целыми числами.

Решение, которое я искал, заключалось в том, чтобы просто округлить нижний предел до ближайшего целого числа, округлить верхний предел до ближайшего целого числа, а затем иметь разрывы в целочисленных значениях между этими конечными точками. Поэтому я использовал функцию перерывов:

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

Требуемый фрагмент кода:

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

Воспроизводимый пример из исходного вопроса:

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
Лучший ответ здесь
Мартин
3

Гугл привел меня к этому вопросу. Я пытаюсь использовать действительные числа в масштабе y. Числа шкалы y указаны в миллионах.

Чешуйки пакет commaметод вводит запятую в моих больших количествах. В этом посте на R-Bloggers объясняется простой подход с использованием commaметода:

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)

Наслаждайтесь R :)

Тони Кронин
источник
1
Другие решения здесь на самом деле не работали для меня или казались смехотворно сложными. Этот работал, и его было просто сделать.
Брайан Доэрти,
спасибо @BrianDoherty, простота - ключ ко многому ...
Тони Кронин,
3

Все существующие ответы, похоже, требуют настраиваемых функций или в некоторых случаях не работают.

Эта строка делает целочисленные разрывы:

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

Для получения дополнительной информации см. Документацию ?labeling::extended(это функция, вызываемая пользователем scales::breaks_extended).

По сути, аргумент Q- это набор хороших чисел, которые алгоритм пытается использовать для разрыва шкалы. Оригинальный сюжет производит нецелые перерывы (0, 2,5, 5 и 7,5) , так как значение по умолчанию для Qвключает в себя 2,5: Q = c(1,5,2,2.5,4,3).

РЕДАКТИРОВАТЬ: как указано в комментарии, нецелочисленные разрывы могут возникать, когда ось Y имеет небольшой диапазон. По умолчанию breaks_extended()пытается сделать около n = 5перерывов, что невозможно при слишком маленьком диапазоне. Быстрое тестирование показывает, что диапазоны шире 0 <y <2,5 дают целочисленные разрывы ( nтакже могут быть уменьшены вручную).

Ник
источник
1

Этот ответ основан на ответе @ Axeman на комментарий Кори о том, что если данные идут только от 0 до 1, разрыв не отображается на 1. Это, по-видимому, из-за неточности prettyс выходами, которые кажутся 1, не идентичными 1 (см. Пример в конце).

Поэтому, если вы используете

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

с участием

+ scale_y_continuous(breaks = int_breaks_rounded)

как 0, так и 1 показаны разрывами.

Пример, иллюстрирующий отличие от Axeman's

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)

Оба будут работать с данными, указанными в первоначальном вопросе.

Иллюстрация того, почему требуется округление

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

Я нашел это решение от Джошуа Кука и работал очень хорошо.

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

Источник: https://joshuacook.netlify.app/post/integer-values-ggplot-axis/

Бруно Видигал
источник