Ответ 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)