4

在绘制条形图时,我经常给条形添加标签以表示每个条形的 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)

reprex 包(v0.3.0)
创建于 2021-01-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", vjust = 1, size = 7)

reprex 包(v0.3.0)
于 2021 年 1 月 25 日创建在 这里,我们看到 for 栏c500文本超出了栏的底部。所以在这种情况下,我也想将geom_text()'s更改vjust0, 仅用于 bar c


总结一下

尽管有一些解决方案可以根据 y 值vjust通过简单的ifelse(请参阅此 SO 解决方案)进行有条件地更改,但我试图弄清楚如何进行调节vjust,以使其无论 y 刻度上的值如何都可以工作。相反,规则应该是,如果栏的高度低于 size of geom_text(),则文本位置将移动到顶部。谢谢!


编辑


根据下面与@Paul 的讨论,我想知道是否可以更容易地vjust确定geom_text()position 是否覆盖y = 0,如果是,则更vjust改为0.


编辑 2


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

4

4 回答 4

5

作为实现所需结果的开箱即用选项,我建议查看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

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

于 2021-01-28T19:04:38.153 回答
1

vjust 也可以采用等于 x 轴大小的输入向量。vjust 的顺序(我放 0 的地方)基于数据集的顺序,而不是 ggplot 中显示的显示。您可以将血型因素考虑在内,以非常具体地说明您希望每个条的位置,并更好地控制 vjust。

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 = c(1,1,1,1,1,1,0,1), size = 7)
于 2021-01-27T13:33:03.830 回答
1

刚刚在谷歌搜索时发现了这个尝试使用vjust = "inward". 但是,这可能会导致其他问题(如此所述)...

ggplot(df_something, aes(x = something, y = quantity)) +
  geom_bar(stat = "identity", fill = "black") +
  geom_text(aes(label = quantity), color = "red", vjust = "inward", size = 7)

在此处输入图像描述

[旧帖子]

我将其发布为“答案”只是为了说明我的意思。它将通过反馈进行改进。

如此处所述,“文本的大小以毫米为单位”。然后,无论您的绘图的最终大小是什么,它都将始终具有相同的大小。

我想我们需要知道您是否必须为您的情节保留最终尺寸。前任:

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

小地块

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

大情节

于 2021-01-27T14:35:39.697 回答
0

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

library(ggplot2)
df_something <- data.frame(something = c("a", "b", "c"),
                           quantity = c(10000, 7800, 500))
ggplot(data = df_something, aes(x = something, y = quantity)) +
  geom_col(position = "dodge", fill = "black") +
  geom_text(
    aes(label = quantity, y = quantity + 50),
    position = position_dodge(0.9),
    vjust = 0,
    color = "red",
    size = 7
  )

在此处输入图像描述

于 2021-01-26T12:27:55.983 回答