Подтвердить что ты не робот

Что такое аргумент width в position_dodge?

Документация не объясняет, что именно это аргумент width

  • Чья ширина указывает?
  • Что такое "единица"?
  • Какое значение по умолчанию?

Значение по умолчанию width = NULL, но пробная версия и ошибка показывают, что width = 0.9, похоже, создает эффект по умолчанию (см. postscript). Однако я не мог найти, где такое значение по умолчанию установлено в ggplot2 исходном коде. Таким образом,

  1. Не могли бы вы объяснить, как утиль по умолчанию реализован в коде ggplot2?

Дух вопроса заключается в том, чтобы позволить пользователям ggplot2 находить соответствующие значения width без проб и ошибок. PS:

ggplot(data = df) +
  geom_bar(aes(x, y, fill = factor(group)), 
           position = position_dodge(), stat = "identity")

ggplot(data = df) +
  geom_bar(aes(x, y, fill = factor(group)), 
           position = position_dodge(0.9), stat = "identity")
4b9b3361

Ответ 1

Сначала я дам краткие ответы на три основных вопроса. Затем я просматриваю несколько примеров, чтобы более подробно проиллюстрировать ответы.

  • Чья ширина указана?
    Ширина элементов, которые нужно уклониться.

  • Что такое "единица"?
    Действительная или виртуальная ширина в единицах данных элементов, которые нужно уклониться.

  • Какое значение по умолчанию? Если вы не устанавливаете уклонение width явно, но полагаетесь на значение по умолчанию, position_dodge(width = NULL) (или просто position = "dodge"), используемая ширина уклонения - это фактическая ширина в единицах данных элемента, который будет уклоняться,

Я считаю, что ваш четвертый вопрос слишком широк для SO. Пожалуйста, обратитесь к коду collide и dodge и, при необходимости, задать новый, более конкретный вопрос.


В зависимости от ширины уклона элемента (вместе с его исходным горизонтальным положением и количеством элементов, которые сложены), новые центральные позиции (x) каждого элемента и новые ширины (xmin, xmax). Элементы сдвигаются горизонтально достаточно далеко, чтобы не перекрываться с соседними элементами. Очевидно, что широкие элементы должны быть сдвинуты более чем узкие элементы, чтобы избежать перекрытия.

Чтобы лучше понять уклонение в целом и использование аргумента width в частности, я приведу несколько примеров. Мы начинаем с простого уклоняющегося штрихового графика с уклонением по умолчанию; мы можем использовать либо position = "dodge", либо более явный position = position_dodge(width = NULL)

# some toy data
df <- data.frame(x = 1,
                 y = 1,
                 grp = c("A", "B"))

p <- ggplot(data = df, aes(x = x, y = y, fill = grp)) + theme_minimal()
p + geom_bar(stat = "identity",
             position = "dodge")
           # which is the same as:
           # position = position_dodge(width = NULL))

введите описание изображения здесь

Итак, (1), кто width находится в position_dodge и (2), что такое единица?

В ?position_dodge мы можем прочитать:

width: ширина уклонения, когда она отличается от ширины отдельных элементов

Таким образом, если мы используем значение по умолчанию width, т.е. NULL, кавычки уклонения основаны на ширине отдельных элементов.

Итак, тривиальный ответ на ваш первый вопрос: "Чью ширину он определяет?" будет: ширина отдельных элементов.

Но, конечно, мы тогда задаемся вопросом: что такое "ширина отдельных элементов"? Начните с баров. Из ?geom_bar:

width: ширина бара. По умолчанию установлено 90% разрешения данных

Возникает новый вопрос: что такое разрешение? Пусть проверка ?ggplot2::resolution:

Разрешение - это наименьшее ненулевое расстояние между смежными значениями. Если есть только одно уникальное значение [как в нашем примере], то разрешение определяется как единое целое.

Мы пытаемся:

resolution(df$x)
# [1] 1

Таким образом, ширина по умолчанию в этом примере равна 0.9 * 1 = 0.9

Мы можем проверить это, посмотрев на данные ggplot, чтобы отображать полосы на графике с помощью ggplot_build. Мы создаем объект сюжета со штабелированным штриховым шрифтом, с полосами по умолчанию.

p2 <- p +
  geom_bar(stat = "identity",
           position = "stack")

Соответствующий слот в объекте $data, который представляет собой список с одним элементом для каждого слоя на графике, в том же порядке, в котором они отображаются в коде. В этом примере у нас есть только один слой, т.е. geom_bar, поэтому посмотрим на первый слот:

ggplot_build(p2)$data[[1]]

#      fill x y label PANEL group ymin ymax xmin xmax colour size linetype alpha
# 1 #F8766D 1 1     A     1     1    0    1 0.55 1.45     NA  0.5        1    NA
# 2 #00BFC4 1 2     B     1     2    1    2 0.55 1.45     NA  0.5        1    NA

Каждая строка содержит данные для "рисования" одной строки. Как вы можете видеть, ширина баров равна 0,9 (xmax - xmin = 0.9). Таким образом, ширина штабелированных стержней, которая будет использоваться при расчетах новых уклоненных позиций и ширины, равна 0.9.


В предыдущем примере мы использовали ширину полосы по умолчанию вместе с шириной уклонения по умолчанию. Теперь позвольте сделать панель немного шире, чем ширина по умолчанию выше (0.9). Используйте аргумент width в geom_bar, чтобы явно установить ширину полосы (уложенной), например 1. Мы пытаемся использовать ту же ширину уклона, что и выше (position_dodge(width = 0.9)). Таким образом, хотя мы установили фактическую ширину полосы равным 1, расчеты уклонения производятся так, как если бы бары имели ширину 0,9. Посмотрим, что получится:

p +
  geom_bar(stat = "identity", width = 1, position = position_dodge(width = 0.9), alpha = 0.8)
p

введите описание изображения здесь

Полосы перекрываются, потому что ggplot сдвигает полосы горизонтально, как если бы они имели (уложенную) ширину 0,9 (задано в position_dodge), а на самом деле полосы имеют ширину 1 (задано в geom_bar).

Если мы используем значения уклонения по умолчанию, полосы сдвигаются горизонтально точно в соответствии с шириной полосы набора:

p +
  geom_bar(stat = "identity", width = 1, position = "dodge", alpha = 0.8)
                                   # or: position = position_dodge(width = NULL)

Затем мы попытаемся добавить текст к нашему сюжету, используя geom_text. Мы начинаем с уклонения по умолчанию width (т.е. position_dodge(width = NULL)), т.е. Уклонение основано на размере элемента по умолчанию.

p <- ggplot(data = df, aes(x = x, y = y, fill = grp, label = grp)) + theme_minimal()
p2 <- p +
  geom_bar(stat = "identity", position = position_dodge(width = NULL)) +
  geom_text(size = 10, position = position_dodge(width = NULL))
                  # or position = "dodge"    

p2
# Warning message:
#  Width not defined. Set with `position_dodge(width = ?)`

введите описание изображения здесь

Уклонение от текста не получается. Как насчет предупреждения? "Ширина не определена?". Немного загадочный. Нам нужно проконсультироваться в разделе "Подробности" ?geom_text:

Обратите внимание, что "ширина" и "высота" текстового элемента равны 0, поэтому укладка и уклонение текста не будут работать по умолчанию, [...] Очевидно, что метки имеют высоту и ширину, но они являются физическими единицами, а не единицами данных.

Итак, для geom_text ширина отдельных элементов равна нулю. Это также первая "официальная ссылка ggplot" на ваш второй вопрос: Единица width находится в единицах данных.

Посмотрите на данные, используемые для визуализации текстовых элементов на графике:

ggplot_build(p3)$data[[2]]
#       fill x y label PANEL group xmin xmax ymax colour size angle hjust vjust alpha family fontface lineheight
# 1 #F8766D 1 1     A     1     1    1    1    1  black   10     0   0.5   0.5    NA               1        1.2
# 2 #00BFC4 1 1     B     1     2    1    1    1  black   10     0   0.5   0.5    NA               1        1.2

Действительно, xmin == xmax; Таким образом, ширина текстового элемента в единицах данных равна нулю.

Как добиться правильного уклонения текстового элемента с нулевой шириной? Из примеров в ?geom_text:

ggplot2 не знает, что вы хотите присвоить ярлыкам ту же виртуальную ширину, что и бары [...] Так скажите:

Таким образом, чтобы dodge использовала ту же ширину для элементов geom_text, что и для элементов geom_bar при вычислении новых позиций, нам нужно установить "виртуальную ширину уклонения в единицах данных" текстового элемента той же ширины, что и бары. Мы используем аргумент width position_dodge, чтобы установить виртуальную ширину текстового элемента равным 0,9 (т.е. Ширину полосы в примере выше):

p2 <- p +
  geom_bar(stat = "identity", position = position_dodge(width = NULL)) +
  geom_text(position = position_dodge(width = 0.9), size = 10)

Проверьте данные, используемые для рендеринга geom_text:

ggplot_build(p2)$data[[2]]
#      fill     x y label PANEL group xmin xmax ymax colour size angle hjust vjust alpha family fontface lineheight
# 1 #F8766D 0.775 1     A     1     1 0.55 1.00    1  black   10     0   0.5   0.5    NA               1        1.2
# 2 #00BFC4 1.225 1     B     1     2 1.00 1.45    1  black   10     0   0.5   0.5    NA               1        1.2

Теперь текстовые элементы имеют ширину в единицах данных: xmax - xmin = 0.9, то есть та же ширина, что и столбцы. Таким образом, расчеты уклонения теперь будут сделаны так, как если бы текстовые элементы имели определенную ширину, здесь 0,9. Извлеките сюжет:

p2

введите описание изображения здесь

Текст уклоняется правильно!


Подобно тексту, ширина в единицах данных точек (geom_point) и барах ошибок (например, geom_errorbar) равна нулю. Таким образом, если вам нужно уклониться от таких элементов, вам нужно указать соответствующую виртуальную ширину, на которой основаны вычисления уклонения. См. Примерный пример ?geom_errorbar:

Если вы хотите уклониться от баров и ошибок, вам нужно вручную указать ширину dodge [...] Поскольку бары и рамки ошибок имеют разную ширину, нам нужно указать, насколько широки объекты, которые мы уклоняемся,


Вот пример с несколькими значениями x в непрерывном масштабе:

df <- data.frame(x = rep(c(10, 20, 50), each = 2),
                 y = 1,
                 grp = c("A", "B"))

Скажем, мы хотим создать уклонившийся барплей с некоторым текстом над каждым баром. Во-первых, просто проверьте штрих-код только с использованием ширины уклонения по умолчанию:

p <- ggplot(data = df, aes(x = x, y = y, fill = grp, label = grp)) + theme_minimal()

p + 
  geom_bar(stat = "identity", position = position_dodge(width = NULL))
                         # or position = "dodge"

Работает так, как ожидалось. Затем добавьте текст. Мы пытаемся установить виртуальную ширину текстового элемента так же, как и ширину столбцов в приведенном выше примере, то есть мы "догадываемся" о том, что бары по-прежнему имеют ширину 0,9 и что нам нужно уклониться от текстовых элементов, как будто они также имеют ширину 0,9:

p +
  geom_bar(stat = "identity", position = "dodge") +
  geom_text(position = position_dodge(width = 0.9), size = 10)

введите описание изображения здесь

Очевидно, что расчет уклонения для баров теперь основан на различной ширине, чем 0,9, а установка виртуальной ширины до 0,9 для текстового элемента была плохой догадкой. Итак, что такое ширина бара? Опять же, ширина бара равна "[b] y по умолчанию, установленному на 90% разрешения данных". Проверьте разрешение:

resolution(df$x)
# [1] 10

Таким образом, ширина (по умолчанию уложенных) баров, на которых вычисляется их новое, уклоненное положение, теперь 0.9 * 10 = 9. Таким образом, чтобы уклониться от баров и их соответствующего текста "рука об руку", нам нужно установить виртуальную ширину также текстовых элементов на 9:

p +
  geom_bar(stat = "identity", position = "dodge") +
  geom_text(position = position_dodge(width = 9), size = 10)

введите описание изображения здесь


В нашем последнем примере у нас есть категориальная ось х, просто "факторная версия" значений х сверху.

df <- data.frame(x = factor(rep(c(10, 20, 50), each = 2)),
                 y = 1,
                 grp = c("A", "B"))

В R факторы являются внутренне набором целочисленных кодов с атрибутом "levels". И от ?resolution:

Если x - целочисленный вектор, то предполагается, что он представляет собой дискретную переменную, а разрешение равно 1.

В настоящее время мы знаем, что когда resolution равно 1, ширина столбца по умолчанию равна 0,9. Таким образом, по категориальной оси x ширина по умолчанию для geom_bar равна 0,9, и нам нужно установить уклонение width для geom_text соответственно:

ggplot(data = df, aes(x = x, y = y, fill = grp, label = grp)) +
  theme_minimal() +
  geom_bar(stat = "identity", position = "dodge") +
  # or: position = position_dodge(width = NULL)
  # or: position = position_dodge(width = 0.9)
  geom_text(position = position_dodge(width = 0.9), size = 10)

введите описание изображения здесь