position_dodge中的width参数是什么?

时间:2016-01-20 01:04:11

标签: r ggplot2

The documentation没有解释这个width参数究竟是什么

  1. 它指定了哪个宽度?
  2. 什么是“单位”?
  3. 什么是默认值?
  4. 默认值为width = NULL,但试验和错误显示width = 0.9似乎产生默认效果(请参阅postscript)。但是,I couldn't find where such default value is set in ggplot2 source code。因此,

    1. 您能解释一下默认闪避是如何在ggplot2代码中实现的吗?
    2. 问题的精神是允许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")
      

1 个答案:

答案 0 :(得分:62)

我将首先简要回答您的三个主要问题。然后,我将通过几个例子来更全面地说明答案。

  1. 指定的宽度
    要躲避的元素的宽度。

  2. "单位"是什么? 实际的要躲避的元素的数据单元中的虚拟宽度。

  3. 什么是默认值
    如果你没有设置明确躲避width,但依赖默认值position_dodge(width = NULL)(或只是position = "dodge"),躲闪宽度使用的是要被躲避的元素的数据单位的实际宽度。

  4. 我相信你的第四个问题对于SO来说过于宽泛。请参阅collidedodge的代码,如果需要,请提出新的,更具体的问题。

    根据元素的躲避宽度(连同其原始水平位置和堆叠的元素数量),每个元素的新中心位置(x)和新宽度({{1}计算},xmin位置)。元素水平移动到足够远,不与相邻元素重叠。显然,宽元素需要比窄元素移位更多,以避免重叠。

    为了更好地感受一般的躲避和特别使用xmax论点,我展示了一些例子。我们从一个简单的躲避条形图开始,默认躲避;我们可以使用width或更明确的position = "dodge"

    position = position_dodge(width = NULL)

    enter image description here

    所以(1)# 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)) width是谁{(1}}和(2)单位是什么?

    position_dodge我们可以阅读:

      

    ?position_dodge:当不同到单个元素的宽度时躲避宽度

    因此,如果我们使用默认 width,即width,则躲避计算基于各个元素的宽度

    对你的第一个问题,&#34; 指定的宽度?这是一个微不足道的答案,将是:各个元素的宽度

    但当然我们想知道,&#34;各个元素的宽度&#34;?让我们从酒吧开始吧。来自NULL

      

    ?geom_bar:条宽。默认情况下,设置为数据分辨率的90%

    出现了一个新问题:决议是什么?我们检查width

      

    分辨率是相邻值之间的最小非零距离。如果只有一个唯一值[如我们的示例中所示],则将分辨率定义为1。

    我们尝试:

    ?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

    每行包含要绘制的数据&#39;一个酒吧。如您所见,条形的宽度均为0.9(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 )。因此,用于计算新的躲避位置和宽度的堆叠条的宽度为xmax - xmin = 0.9

    在上一个示例中,我们使用默认的条形宽度以及默认的闪避宽度。现在让我们使条形略宽于上面的默认宽度(0.9)。使用0.9中的width参数明确设置(堆积)条形宽度为例如1.我们尝试使用与上面相同的闪避宽度(geom_bar )。因此,虽然我们实际条宽度设置为1,但是闪避计算就好像条的宽度为0.9。让我们看看会发生什么:

    position_dodge(width = 0.9)

    enter image description here

    条形图是重叠的,因为ggplot水平移动条形,好像它们的(堆叠)宽度为0.9( set p + geom_bar(stat = "identity", width = 1, position = position_dodge(width = 0.9), alpha = 0.8) p 中),而实际上条形的宽度为1(position_dodge中的 set )。

    如果我们使用默认减淡值,则根据 set 条宽度水平移动条形:

    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)

    enter image description here

    文本的躲避失败了。警告信息怎么样? &#34;未定义宽度?&#34;。有点神秘。我们需要查看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 = ?)` 的详细信息部分:

      

    注意&#34;宽度&#34;和&#34;身高&#34;一个文本元素是0,   所以堆叠和躲避文本默认不起作用,   [...]   显然,标签确实有高度和宽度,但它们是物理单位,不是数据单位

    因此对于?geom_text各个元素的宽度为零。这也是第一个官方ggplot参考&#39;至于您的第二个问题: geom_text的单位是数据单位

    让我们看看用于渲染图上文字元素的数据:

    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中的示例:

      

    ggplot2并不知道你想给标签提供与条形图相同的虚拟宽度[...]所以告诉它:

    因此,为了使躲闪在计算新位置时?geom_text元素使用与geom_text元素相同的宽度,我们需要设置&#34 ;数据单元中的虚拟躲避宽度&#34;文本元素的宽度与条形相同。我们使用geom_bar的{​​{1}}参数将设置文本元素的虚拟宽度设置为0.9(即上例中的条宽):

    width

    检查用于渲染position_dodge的数据:

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

    现在,文本元素具有数据单位的宽度:geom_text,即与条形图相同的宽度。因此,现在闪避计算就好像文本元素具有一定的宽度,这里是0.9。渲染情节:

    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
    

    enter image description here

    文字被正确躲闪!

    与文本类似,点(xmax - xmin = 0.9)和误差线(例如p2 )的数据单位宽度为零。因此,如果你需要躲避这些元素,你需要指定一个相关的虚拟宽度,然后根据闪避计算。参见例如geom_point的示例部分:

      

    如果你想躲避条形和错误条,你需要手动指定躲避宽度[...]因为条形和错误条具有不同的宽度,我们需要指定我们躲避的物体的宽度

    这是一个连续刻度上有几个x值的例子:

    geom_errorbar

    让我们说我们希望创建一个躲避的条形图,每个条形图上方都有一些文字。首先,只使用默认的躲避宽度检查条形图:

    ?geom_errorbar

    它按预期工作。然后,添加文本。我们尝试将文本元素的虚拟宽度设置为与上面示例中的条形宽度相同,即我们猜测&#34;条形仍然有0.9的宽度,我们需要躲避文本元素,就像它们的宽度也是0.9一样:

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

    enter image description here

    显然,条形的躲避计算现在基于不同的宽度而不是0.9,并且将文本元素的虚拟宽度设置为0.9是一个糟糕的猜测。那么 条宽度在这里是什么?同样,条形宽度为&#34; [b] y默认值,设置为数据分辨率的90%&#34;。检查分辨率:

    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"
    

    因此,计算新的躲避位置的(默认堆叠)条的宽度现在为p + geom_bar(stat = "identity", position = "dodge") + geom_text(position = position_dodge(width = 0.9), size = 10) 。因此,为了躲避条形图及其相应的文本,我们需要将文本元素的虚拟宽度设置为9:

    resolution(df$x)
    # [1] 10
    

    enter image description here

    在我们的最后一个例子中,我们有一个分类的x轴,只是一个因子版本&#39;来自上面的x值。

    0.9 * 10 = 9

    在R中,因子在内部是一组带有&#34;等级的整数代码&#34;属性。来自p + geom_bar(stat = "identity", position = "dodge") + geom_text(position = position_dodge(width = 9), size = 10)

      

    如果x是整数向量,则假定它代表离散变量,分辨率为1.

    到目前为止,我们知道当df <- data.frame(x = factor(rep(c(10, 20, 50), each = 2)), y = 1, grp = c("A", "B")) 为1时,条形的默认宽度为0.9。因此,在分类x轴上,?resolution的默认宽度为0.9,我们需要相应地为resolution设置躲避geom_bar

    width

    enter image description here