>它指定的宽度是多少?
>什么是“单位”?
>什么是默认值?
默认值为width = NULL,但试验和错误显示width = 0.9似乎产生默认效果(请参阅postscript)。然而,I couldn’t find where such default value is set in ggplot2
source code.因此,
>你能解释ggplot2代码中如何实现默认闪避吗?
这个问题的精神在于允许ggplot2用户找到适合的宽度值,而无需试验和错误。
PS:
ggplot(data = df) + geom_bar(aes(x,y,fill = factor(group)),position = position_dodge(),stat = "identity") ggplot(data = df) + geom_bar(aes(x,position = position_dodge(0.9),stat = "identity")
解决方法
>它指定的宽度是多少?
要躲避的元素的宽度。
>什么是“单位”?
要躲避的元素的数据单位的实际或虚拟宽度。
>什么是默认值?
如果没有明确设置躲避宽度,但是依赖于默认值position_dodge(width = NULL)(或者只是position =“躲避”),所使用的闪避宽度是元素的数据单位的实际宽度被躲避
我相信你的第四个问题太过分广泛了。请参阅collide
和dodge
的代码,如果需要,请提出一个新的更具体的问题。
基于元素的闪避宽度(连同其原始水平位置和堆叠元素的数量),计算每个元素的新的中心位置(x)和新的宽度(xmin,xmax位置)。元素水平移动到足够远,不与相邻元素重叠。显然,广泛的元素需要比狭窄的元素更多地转移,以避免重叠。
为了获得更好的躲避感,特别是使用宽度参数,我举一些例子。我们从一个简单的闪避酒吧开始,默认闪避;我们可以使用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)谁的宽度是在position_dodge和(2)什么是单位?
在?position_dodge中,我们可以看到:
width
: Dodging width,when different to the width of the individual elements
因此,如果我们使用默认宽度,即NULL,则闪避计数基于各个元素的宽度。
所以你的第一个问题,“它的宽度,它指定吗?”的一个微不足道的答案将是:单个元素的宽度。
但是,当然我们想知道,“单个元素的宽度”是多少?我们从酒吧开始吧。来自?geom_bar:
width
: Bar width. By default,set to 90% of the resolution of the data
出现一个新问题:什么是决议?我们来看看ggplot2 :: resolution:
The resolution is is the smallest non-zero distance between adjacent values. If there is only one unique value [like in our example],then the resolution is defined to be one.
我们尝试:
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)以上的默认宽度。使用geom_bar中的width参数来明确地将(堆叠)条宽设置为例如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",position = "dodge",alpha = 0.8) # or: position = position_dodge(width = NULL)
接下来,我们尝试使用geom_text将一些文本添加到我们的图。我们从默认的闪避宽度开始(即position_dodge(width = NULL)),即避免是基于默认元素大小。
p <- ggplot(data = df,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的Details部分:
Note the the “width” and “height” of a text element are 0,
so stacking and dodging text will not work by default,
[…]
ObvIoUsly,labels do have height and width,but they are physical units,not data units.
所以对于geom_text,单个元素的宽度为零。这也是您第二个问题的第一个“官方ggplot参考”:宽度单位是数据单位。
我们来看一下用于在图上渲染文本元素的数据:
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 doesn’t know you want to give the labels the same virtual width as the bars […] So tell it:
因此,为了避免在计算新位置时避免对Geom_bar元素使用与geom_bar元素相同的宽度,我们需要将文本元素的“虚拟闪避宽度”设置为与条纹相同的宽度。我们使用position_dodge的width参数将文本元素的虚拟宽度设置为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的示例部分:
If you want to dodge bars and errorbars,you need to manually specify the dodge width […] Because the bars and errorbars have different widths we need to specify how wide the objects we are dodging are
以下是连续比例的几个x值的示例:
df <- data.frame(x = rep(c(10,20,50),each = 2),"B"))
假设我们希望创建一个闪烁的barplot,每个酒吧上方都有一些文字。首先,只需使用默认的躲避宽度检查一个barplot:
p <- ggplot(data = df,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)
在我们的最后一个例子中,我们有一个分类x轴,只是上面x值的“因子版本”。
df <- data.frame(x = factor(rep(c(10,each = 2)),"B"))
在R中,因素在内部是一组具有“levels”属性的整数代码。和从?决议:
If x is an integer vector,then it is assumed to represent a discrete variable,and the resolution is 1.
现在我们知道当分辨率为1时,条的默认宽度为0.9。因此,在分类x轴上,geom_bar的默认宽度为0.9,我们需要相应地设置geom_text的躲避宽度:
ggplot(data = df,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)