如何解决ggplot2:当低条使文本超过条的底部时,如何有条件地更改 geom_text 的 vjust
在绘制条形图时,我经常为条形添加标签以表示每个条形的 y 值。但是,当条形变得太低时,我会遇到麻烦,使标签变得不可读或难看。
示例
library(ggplot2)
df_blood <- data.frame(blood_type = c("O-","O+","A-","A+","B-","B+","AB-","AB+"),frequency = c(0.13,0.35,0.08,0.3,0.02,0.01,0.02))
ggplot(df_blood,aes(x = blood_type,y = frequency,fill = blood_type)) +
geom_bar(stat = "identity") +
geom_text(aes(label = frequency),color = "blue",vjust = 1,size = 7)
由 reprex package (v0.3.0) 于 2021 年 1 月 25 日创建
查看 AB-
的栏,我们可以看到 0.01
文本超出了栏的高度(在栏的底部)。在这种情况下,我想将 vjust
的 geom_text()
更改为 0
。
另一个具有不同 y 比例的示例
这里我对 size = 7
使用与上面相同的 geom_text()
:
library(ggplot2)
df_something <- data.frame(something = c("a","b","c"),quantity = c(10000,7800,500))
ggplot(df_something,aes(x = something,y = quantity)) +
geom_bar(stat = "identity",fill = "black") +
geom_text(aes(label = quantity),color = "red",size = 7)
由 reprex package (v0.3.0) 于 2021 年 1 月 25 日创建
在这里,我们看到 c
栏的 500
文本超出了栏的底部。因此,在这种情况下,我还想将 geom_text()
的 vjust
更改为 0
,仅用于栏 c
。
总结
虽然有一些解决方案可以根据 y 值使用简单的 vjust
(请参阅 this SO solution)有条件地更改 ifelse
,但我试图弄清楚如何调节 {{ 1}} 这样无论 y 尺度上的值如何,它都可以工作。相反,规则应该是,如果条的高度低于 vjust
的大小,则文本位置将移动到顶部。谢谢!
编辑
基于下面与@Paul 的讨论,我想知道是否可以更容易地将 geom_text()
的位置设置为 vjust
位置是否覆盖 geom_text()
,如果是,则更改 {{1 }} 到 y = 0
。
编辑 2
This SO solution(归功于 @Paul 的发现)似乎与我的要求非常接近。它动态更改 vjust
的 0
以适应条宽,并且即使在调整绘图大小时也能正常工作。所以我认为这为我所追求的提供了基础,而不是调整 size
,我需要调整 geom_text()
,而不是根据条宽调整它,我需要根据条高调整它。不幸的是,对于我对 size
等的理解,它太复杂了,所以我不知道如何使它适应我的情况。
解决方法
作为实现您想要的结果的开箱即用选项,我建议查看 ggfittext
包,该包有一些选项可以将标签放在条形之外适合内部或缩小标签。此外,还有一些选项可以在标签周围添加一些填充。但是,它使用无默认大小策略,因此您必须将默认单位乘以 ggplot2::.pt
:
library(ggplot2)
library(ggfittext)
df_something <- data.frame(something = c("a","b","c"),quantity = c(10000,7800,500))
ggplot(df_something,aes(x = something,y = quantity)) +
geom_bar(stat = "identity",fill = "black") +
geom_bar_text(aes(label = quantity),color = "red",vjust = 1,size = 7 * ggplot2::.pt,min.size = 7 * ggplot2::.pt,padding.x = grid::unit(0,"pt"),padding.y = grid::unit(0,outside = TRUE)
#> Warning: Ignoring unknown aesthetics: label
df_blood <- data.frame(blood_type = c("O-","O+","A-","A+","B-","B+","AB-","AB+"),frequency = c(0.13,0.35,0.08,0.3,0.02,0.01,0.02))
ggplot(df_blood,aes(x = blood_type,y = frequency,fill = blood_type)) +
geom_bar(stat = "identity") +
geom_bar_text(aes(label = frequency),color = "blue",outside = TRUE)
#> Warning: Ignoring unknown aesthetics: label
,
vjust 也可以采用等于 x 轴大小的输入向量。 vjust(我放 0 的位置)的顺序基于数据集的顺序,而不是 ggplot 中显示的显示。您可以将血型分解为非常具体的关于您希望每个条位于何处的因素,并更好地控制 v。
library(ggplot2)
df_blood <- data.frame(blood_type = c("O-",fill = blood_type)) +
geom_bar(stat = "identity") +
geom_text(aes(label = frequency),vjust = c(1,1,1),size = 7)
,
刚在 googling around 时发现了这个:
尝试使用 vjust = "inward"
。但是,这可能会导致其他问题(如here 所述)...
ggplot(df_something,fill = "black") +
geom_text(aes(label = quantity),vjust = "inward",size = 7)
[旧帖子]
我将此作为“答案”发布只是为了表明我的意思。将根据反馈改进。
如 here 所述,“文本的大小以毫米为单位”。那么无论您的图的最终尺寸是多少,它都将始终具有相同的尺寸。
我想我们需要知道你是否必须为你的情节保留一个最终的维度。 例如:
ggsave(filename = "test_small.png",height = 5,units = "cm")
ggsave(filename = "test_big.png",height = 20,units = "cm")
,
您可以将标签放在列中而不是将它们放在顶部,这样就可以解决您的问题吗?它适用于所有列,您无需担心选择单个列。将所有标签放在上面可能更干净,而不是在上面放一些标签。
library(ggplot2)
df_something <- data.frame(something = c("a",500))
ggplot(data = df_something,y = quantity)) +
geom_col(position = "dodge",fill = "black") +
geom_text(
aes(label = quantity,y = quantity + 50),position = position_dodge(0.9),vjust = 0,size = 7
)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。