我一直在绞尽脑汁地思考一个问题,那就是在geom_col图上向外对齐geom_text标签.我做了一个重现我问题的MWE.问题是,我在正负两个区域都有列,and一些负值比正值大得多,把我轴的"0"标记移到了一边.

以下是常规设置(请注意,我使用的是Windows 11,使用的是R版本4.2.2)和数据:

library(ggplot2)
library(dplyr)
library(tidyr)
ggplot2::theme_set(theme_minimal())

df <- tibble(period = c("one_y", "three_y", "five_y", "seven_y", "ten_y", "whole_period"),
             nominal_gross = c(-21.13, NA, NA, 3.04, 4.1, 4),
             nominal_net = c(-21.64, -3.48, 0.6, 2.58, 3.69, 3.7),
             real_net = c(-25.65, -8.97, -3.75, -0.89, 1.04, 1.25)) %>%
  pivot_longer(!period, names_to = "return_type", values_to = "return_values")

我曾try 使用hjust="outward",但据我所知,该命令不以轴上的"0"为参考,而是以绘图区的中点(在我的例子中约为-10)为参考.下面是代码,我插入下面的结果图:

ggplot(data = df, 
       mapping = aes(
         x = factor(period, 
                  levels = rev(c("one_y", "three_y", "five_y", "seven_y", "ten_y", "whole_period")),
                  labels = rev(c("1 year", "3 years", "5 years", "7 years", "10 years", "Whole period"))),
         y = return_values, 
         label = scales::label_percent(scale = 1)(return_values),
         fill = return_type)) +
  geom_col(position = position_dodge2(reverse = T), na.rm = T) +
  geom_text(position = position_dodge2(reverse = T, width = 0.9),
            na.rm = T,
            hjust = "outward", 
            vjust = 0.4,
            size = 3,
            check_overlap = T) +
  scale_fill_manual(values = c("#006FB4", "darkgrey", "#01416B"), 
                    labels = c("Nominal gross", "Nominal net", "Real net"),
                    name = NULL) +   
  scale_y_continuous(n.breaks = 10,
                     expand = expansion(add = ifelse(max(abs(df$return_values), na.rm = T)> 10, 3.5, 2)),
                     labels = scales::label_percent(scale = 1)) +
  labs(x = NULL, y = "Annualised returns") +
    coord_flip()

Plot with

结果没那么差,but我的负值在0到-10之间的标签在条里面…… 然后我试着用ifelsehjust变成return_values的条件.同样,以下是代码和生成的图表:

ggplot(data = df, 
       mapping = aes(
         x = factor(period, 
                    levels = rev(c("one_y", "three_y", "five_y", "seven_y", "ten_y", "whole_period")),
                    labels = rev(c("1 year", "3 years", "5 years", "7 years", "10 years", "Whole period"))),
         y = return_values, 
         label = scales::label_percent(scale = 1)(return_values),
         fill = return_type)) +
  geom_col(position = position_dodge2(reverse = T)) +
  geom_text(position = position_dodge2(reverse = T, width = 0.9),
            hjust = ifelse(test = df$return_values < 0, yes = 1.25, no = -0.25),
            vjust = 0.4,
            size = 3,
            check_overlap = T) +
  scale_fill_manual(values = c("#006FB4", "darkgrey", "#01416B"), 
                    labels = c("Nominal gross", "Nominal net", "Real net"),
                    name = NULL) +   
  scale_y_continuous(n.breaks = 10,
                     expand = expansion(add = ifelse(max(abs(df$return_values), na.rm = T)> 10, 3.5, 2)),
                     labels = scales::label_percent(scale = 1)) +
  labs(x = NULL, y = "Annualised returns") +
  coord_flip()

Plot with

这实际上更糟糕:我的大部分标签现在都在wine 吧里,但有些放在了正确的位置.然后,我得出结论,我的条件语句存在问题.我曾try 删除Nas,以用零替换Nas,但我找不到问题的根源.如果有人能帮我找到解决方案,我将不胜感激.

请注意,如果有一种方法可以通过"打断"轴并删除-10到-20之间的区域来对绘图进行"裁剪",我也希望如此(下图中两条黑线之间的区域).我try 过将限制设置在scale_y_continuous以内,并使用了oob参数,但在我try 过的所有解决方案中,最长的条形图似乎就停在了限制值上,并且我失go 了三者之间的渐变.

Plot with ifelse cropping

EDIT

实际上,我刚刚找到了答案:条件语句必须传递给geom_text,并带有hust作为美学:

geom_text(aes(hjust = ifelse(return_values < 0, 1.25, -0.25)),
            position = position_dodge2(reverse = T, width = 0.9),
            vjust = 0.4,
            size = 3,
            check_overlap = T) 

那么它就运行得很好.

推荐答案

如果您希望标签位于负值的左侧,正值的右侧,您可以将hjust合并到aes()中--这将比引用df$return_values更一致,因为它将使用与条形图相同的顺序,这可能与原始数据中的顺序不一致.

  ggplot(data = df, 
         mapping = aes(
           x = factor(period, 
                      levels = rev(c("one_y", "three_y", "five_y", "seven_y", "ten_y", "whole_period")),
                      labels = rev(c("1 year", "3 years", "5 years", "7 years", "10 years", "Whole period"))),
           y = return_values, 
           label = scales::label_percent(scale = 1)(return_values),
           fill = return_type)) +
  geom_col(position = position_dodge2(reverse = T), na.rm = T) +
  geom_text(position = position_dodge2(reverse = T, width = 0.9),
            na.rm = T,
            aes(hjust = ifelse(return_values < 0, 1.1, -0.1)),  ##### SEE HERE #####
            vjust = 0.4,
            size = 3,
            check_overlap = T) +
  scale_fill_manual(values = c("#006FB4", "darkgrey", "#01416B"), 
                    labels = c("Nominal gross", "Nominal net", "Real net"),
                    name = NULL) +   
  scale_y_continuous(n.breaks = 10,
                     expand = expansion(add = ifelse(max(abs(df$return_values), na.rm = T)> 10, 3.5, 2)),
                     labels = scales::label_percent(scale = 1)) +
  labs(x = NULL, y = "Annualised returns") +
  coord_flip(clip = "off")                                 ##### SEE HERE #####
  

enter image description here

R相关问答推荐

如何修复R码的置换部分?

在"gt"表中添加第二个"groupname_col",而不连接列值

当两个图层映射到相同的美学时,隐藏一个图层的图例值

如何将移除事件分配给动态创建的按钮?

使用ggsankey调整Sankey图中单个 node 上的标签

从BRM预测价值

为了网络分析目的,将数据框转换为长格式列联表

为什么我使用geom_density的绘图不能到达x轴?

有没有可能用shiny 的书签恢复手风琴面板?

按列中显示的配对组估算NA值

警告消息";没有非缺失的参数到min;,正在返回数据中的inf";.表分组集

如何在PrePlot()中将多个元素设置为斜体

如何将EC50值绘制在R中的剂量-react 曲线上?

按镜像列值自定义行顺序

如何在R中使用因子行求和?

如何计算多个变量的百分比与总和的百分比?

对数据帧中的列进行子集设置以通过迭代创建新的数据帧

只有当我在循环的末尾放置一条print语句时,Foreach才会给出预期的输出

如何根据列名和行名求和矩阵的值?

列中的所有值都是真的吗?忽略NA