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

Emm*_*man 8 r ggplot2 geom-text ggproto

绘制条形图时,我经常向条形图添加标签以表示每个条形图的 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.08, 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)
Run Code Online (Sandbox Code Playgroud)

由reprex 包(v0.3.0)于 2021-01-25 创建
。查看 的栏AB-,我们可以看到文本0.01超出了栏的高度(在栏的底部)。在这种情况下,我想将vjustof更改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", vjust = 1, size = 7)
Run Code Online (Sandbox Code Playgroud)

由reprex 包(v0.3.0)创建于 2021-01-25
这里我们看到 的栏的c文本500超出了栏的底部。因此,在这种情况下,我还想将geom_text()'s更改vjust0, 仅适用于酒吧c


总结

尽管有一些解决方案可以根据 y 值进行vjust简单的有条件更改ifelse(请参阅此 SO 解决方案),但我正在尝试找出如何进行调节,vjust以便无论 y 刻度上的值如何,它都可以工作。相反,规则应该是,如果栏的高度低于 的大小geom_text(),则文本位置将移动到顶部。谢谢!


编辑


根据下面与@Paul的讨论,我想知道是否可以更容易地条件化位置vjust是否覆盖,如果是,则更改为。geom_text()y = 0vjust0


编辑2


这个 SO 解决方案(归功于@Paul的发现)似乎与我所要求的足够接近。它动态地改变 的sizegeom_text()适应条形宽度,并且即使在调整绘图大小时也能工作。所以我认为这为我所追求的提供了基础,只是size我需要调整而不是调整vjust,而不是根据条形宽度调节它,我需要根据条形高度调节它。不幸的是,它对于我的理解来说太复杂了ggproto,所以我不知道如何使其适应我的情况。

ste*_*fan 7

作为实现您想要的结果的开箱即用选项,我建议您看一下包装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, "pt"),
                outside = TRUE)
#> Warning: Ignoring unknown aesthetics: label
Run Code Online (Sandbox Code Playgroud)

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.08, 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", 
                vjust = 1, 
                size = 7 * ggplot2::.pt, 
                min.size = 7 * ggplot2::.pt,
                padding.x = grid::unit(0, "pt"),
                padding.y = grid::unit(0, "pt"),
                outside = TRUE)
#> Warning: Ignoring unknown aesthetics: label
Run Code Online (Sandbox Code Playgroud)

  • 嗨艾曼。默认情况下,我的意思是在 ggplot2 中,所有尺寸都以“mm”为单位测量,包括字体大小。请参阅[此处](https://ggplot2.tidyverse.org/articles/ggplot2-specs.html#font-size-1)。为了方便起见,ggplot2 提供了常量 `.pt` 将“mm”转换为更常见的“pt”或“点”,即如果您想要“7pt”的字体大小,您可以执行 `size = 7 / .pt` 。话虽如此,在非默认情况下,我的意思是 `ggfittext` 使用“pt”作为 fontsite 的单位,即 `size = 7` 将为您提供大小为 7pt 的字体。因此,如果您想要“默认”ggplot2 大小,则必须乘以“.pt”。有点混乱,但是.. (2认同)