如何在横杠中对齐标签

时间:2018-09-27 19:30:45

标签: r ggplot2

我正在尝试将三个文本标签对齐,即均值,中位数和当前值在交叉开关之外。感谢您的帮助。

我的数据

structure(list(variable = structure(1:10, .Label = c("GrossNetEquity", 
"GrossTotalEquityPerfAttr", "LongNetEquity", "LongTotalEquity", 
"NetEquity", "NetEquityPerfAttr", "NetTotalEquity", "ShortNetEquity", 
"ShortTotalEquity", "TotalNetEquity"), class = "factor"), mx = c(134.5, 
8.1, 95.6, 106.4, 61, 6.8, 71.6, -21.4, -24.9, 148.7), mn = c(71.1, 
-4.6, 49.7, 66.2, 27, -4.1, 36.4, -46.3, -47.4, 96), avg = c(112.173148148148, 
1.14814814814815, 77.7388888888889, 84.5111111111111, 43.262037037037, 
1.05092592592593, 48.0694444444444, -34.4194444444444, -36.4416666666667, 
120.952777777778), sd = c(14.5968093202928, 2.39877232936504, 
9.87368667081958, 8.7204382695887, 7.29159953981859, 2.24405738054356, 
7.05196278547511, 6.04899711056417, 5.77265751334298, 13.0003483658092
), md = c(114.15, 1.4, 77.35, 82.65, 41.45, 1.25, 46.35, -34.1, 
-35.55, 119.75), firstldiff = c(82.9795295075625, -3.64939651058193, 
57.9915155472497, 67.0702345719337, 28.6788379573998, -3.4371888351612, 
33.9655188734942, -46.5174386655728, -47.9869816933526, 94.9520810461593
), firstlsum = c(141.366766788734, 5.94569280687823, 97.4862622305281, 
101.951987650289, 57.8452361166742, 5.53904068701305, 62.1733700153947, 
-22.3214502233161, -24.8963516399807, 146.953474509396), secldiff = c(68.3827201872697, 
-6.04816883994697, 48.1178288764302, 58.349796302345, 21.3872384175813, 
-5.68124621570476, 26.9135560880191, -52.566435776137, -53.7596392066956, 
81.9517326803501), seclsum = c(155.963576109027, 8.34446513624327, 
107.359948901348, 110.672425919877, 65.1368356564928, 7.78309806755661, 
69.2253328008698, -16.2724531127519, -19.1236941266377, 159.953822875205
), value = c(116.1, -1.2, 88, 92.3, 58.8, -1.2, 63, -28.1, -29.3, 
121.6), Criteria = c(NA, NA, "", "", "orange", "", "orange", 
"orange", "", "orange")), .Names = c("variable", "mx", "mn", 
"avg", "sd", "md", "firstldiff", "firstlsum", "secldiff", "seclsum", 
"value", "Criteria"), row.names = c(NA, -10L), class = "data.frame")

我的代码 我试图在geom_crossbar上以条形显示均值,中位数和当前值。但是很难对齐。

ggplot(df3,aes(variable,mn))+
  geom_crossbar(aes(ymin = mn, ymax = mx,fill = Criteria),
                width = 0.5,alpha = 0.50,position =position_dodge())+
  geom_point(data=df3, aes(x=variable,y=md,group=1),
             shape = "|", size = 10,color ="brown1")+
  geom_text(data=df3, aes(x=variable, y=md, label = paste("Median",md)), 
            size = 3, vjust = 2,hjust = -1.0,color = "brown1",
            position = position_dodge(width=0.9))+
  geom_point(data=df3, aes(x=variable,y=avg,group=1),
             shape = "|", size = 10,color = "coral4")+
  geom_text(data=df3, aes(x=variable, y=avg, label = paste("Mean",mn)),
            size = 3, vjust = 2.5, hjust = -1.0,color ="coral4")+
  geom_point(data=df3, aes(x=variable,y=value,group=1),
             shape = "|", size = 10,color ="brown1")+
  geom_text(data=df3,aes(x=variable, y=value,label = paste("Current Value",value)), 
            size = 2, vjust = 3, hjust = -1.0,color = "brown1")+
  coord_flip()

1 个答案:

答案 0 :(得分:0)

如果希望对齐geom_text图层,则可以为其分配相同的y值。我在下面提供了一个示例。我还从代码中删除了一些重复的部分,使不同的层可以从顶层ggplot()继承数据/美学映射。

ggplot(df3, aes(variable, mx))+

  geom_crossbar(aes(ymin = mn, ymax = mx, fill = Criteria),
                width = 0.5, alpha = 0.50, position = position_dodge()) +

  # vertical bars
  geom_point(aes(y = md), shape = "|", size = 10, color ="brown1") +
  geom_point(aes(y = avg), shape = "|", size = 10, color = "coral4") +
  geom_point(aes(y = value), shape = "|", size = 10, color ="brown1") +

  # labels (vjust used to move the three layers vertically away from one another; 
  # nudge_y used to shift them uniformly rightwards)
  # note that the original label for "Mean" used paste("Mean", mn), but that didn't
  # look right to me, since the vertical bar above used avg instead of mn, & mn appears
  # to correspond to "min", not "mean".
  geom_text(aes(label = paste("Median", md)),
            size = 3, vjust = -1, nudge_y = 5, hjust = 0, color = "brown1") +
  geom_text(aes(label = paste("Mean", avg)),
            size = 3, vjust = 0, nudge_y = 5, hjust = 0, color ="coral4") +
  geom_text(aes(label = paste("Current Value", value)),
            size = 2, vjust = 1, nudge_y = 5, hjust = 0, color = "brown1") +

  coord_flip() +
  expand_limits(y = 200) # expand rightwards to give more space for labels

plot

注意:上面的代码采用了这种方法,该方法对宽格式数据中的不同列重复相同的geom层。通常,ggplot倾向于处理 long 格式的数据。它看起来更干净,并且维护起来更容易,因为您只需要进行一次更改(例如,增加字体大小,更改标签中的小数位数),而不是对每个受影响的图层重复进行更改。解决此问题的长格式方法如下所示:

# create long format data frame for labels
df3.labels <- df3 %>%
  select(variable, mx, md, avg, value) %>%
  tidyr::gather(type, value, -variable, -mx) %>%
  mutate(label = paste0(case_when(type == "md" ~ "Median",
                                  type == "avg" ~ "Mean",
                                  TRUE ~ "Current Value"),
                        ": ",
                        round(value, 2)),
         vjust = case_when(type == "md" ~ -1,
                           type == "avg" ~ 0,
                           TRUE ~ 1))

# place df3.labels in the top level call, since there are two geom layers that 
# use it as the data source, & only one that uses df3.
ggplot(df3.labels,
       aes(x = variable, y = value, color = type, label = label)) +  
  geom_crossbar(data = df3, 
                aes(x = variable, y = mn, ymin = mn, ymax = mx, fill = Criteria),
                inherit.aes = FALSE,
                width = 0.5, alpha = 0.50) +  
  geom_point(shape = "|", size = 10) +
  geom_text(aes(y = mx, vjust = vjust), size = 3, nudge_y = 5, hjust = 0) +

  # change colour mappings here
  scale_color_manual(values = c("md" = "brown1", "avg" = "coral4", "value" = "brown1"),
                     guide = FALSE) +
  coord_flip() +
  expand_limits(y = 200)