微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ggplot2:当低条使文本超过条的底部时,如何有条件地更改 geom_text 的 vjust

如何解决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 文本超出了栏的高度(在栏的底部)。在这种情况下,我想将 vjustgeom_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 的发现)似乎与我的要求非常接近。它动态更改 vjust0 以适应条宽,并且即使在调整绘图大小时也能正常工作。所以我认为这为我所追求的提供了基础,而不是调整 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)

enter image description here

[旧帖子]

我将此作为“答案”发布只是为了表明我的意思。将根据反馈改进。

here 所述,“文本的大小以毫米为单位”。那么无论您的图的最终尺寸是多少,它都将始终具有相同的尺寸。

我想我们需要知道你是否必须为你的情节保留一个最终的维度。 例如:

ggsave(filename = "test_small.png",height = 5,units = "cm")

Small plot

ggsave(filename = "test_big.png",height = 20,units = "cm")

Big plot

,

您可以将标签放在列中而不是将它们放在顶部,这样就可以解决您的问题吗?它适用于所有列,您无需担心选择单个列。将所有标签放在上面可能更干净,而不是在上面放一些标签。

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
  )

enter image description here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。