3

我正在尝试在 ggplot 中创建条形图,其中条形的宽度与变量相关联Cost$Sum.of.FS_P_Reduction_Kg。我正在使用参数width=Sum.of.FS_P_Reduction_Kg根据变量设置条的宽度。

我想在图表中添加直接标签以标记每个条形,类似于下面记录的图像。我也在寻求添加与参数相对应的 x 轴标签width=Sum.of.FS_P_Reduction_Kg.任何帮助将不胜感激。我知道ggrepel但到目前为止还没有达到预期的效果。

带有直接标签和数字 x 轴的图形示例

我使用了以下代码:

# Plot the data 
P1 <- ggplot(Cost,
       aes(x = Row.Labels,
           y = Average.of.Cost_Per_Kg_P_Removal.undiscounted..LOW_Oncost,
           width = Average.of.FS_Annual_P_Reduction_Kg, label = Row.Labels)) +
  geom_col(fill = "grey", colour = "black") + 
  geom_label_repel(
    arrow = arrow(length = unit(0.03, "npc"), type = "closed", ends = "first"),
    force = 10,
    xlim  = NA) +
  facet_grid(~reorder(Row.Labels, 
                      Average.of.Cost_Per_Kg_P_Removal.undiscounted..LOW_Oncost), 
             scales = "free_x", space = "free_x") +
  labs(x = "Measure code and average P reduction (kg/P/yr)",
       y = "Mean annual TOTEX (£/kg) of P removal (thousands)") +
  coord_cartesian(expand = FALSE) +     # remove spacing within each facet
  theme_classic() +
  theme(strip.text = element_blank(),   # hide facet title (since it's same as x label anyway)
        panel.spacing = unit(0, "pt"),  # remove spacing between facets
        plot.margin = unit(c(rep(5.5, 3), 10), "pt"), # more space on left for axis label
        axis.title=element_text(size=14),
        axis.text.y = element_text(size=12),
        axis.text.x = element_text(size=12, angle=45, vjust=0.2, hjust=0.1)) + 
  scale_x_discrete(labels = function(x) str_wrap(x, width = 10))

P1 = P1 + scale_y_continuous(labels = function(x) format(x/1000))
P1

可以使用以下代码复制示例数据表:

> dput(Cost)
structure(list(Row.Labels = structure(c(1L, 2L, 6L, 9L, 4L, 3L, 
5L, 7L, 8L), .Label = c("Change the way P is applied", "Improve management of manure", 
"In channel measures to slow flow", "Keep stock away from watercourses", 
"No till trial ", "Reduce runoff from tracks and gateways", "Reversion to different vegetation", 
"Using buffer strips to intercept pollutants", "Water features to intercept pollutants"
), class = "factor"), Average.of.FS_Annual_P_Reduction_Kg = c(0.11, 
1.5425, 1.943, 3.560408144, 1.239230769, 18.49, 0.091238043, 
1.117113762, 0.11033263), Average.of.FS_._Change = c(0.07, 0.975555556, 
1.442, 1.071692763, 1.212307692, 8.82, 0.069972352, 0.545940711, 
0.098636339), Average.of.Cost_Per_Kg_P_Removal.undiscounted..LOW_Oncost = c(2792.929621, 
2550.611429, 964.061346, 9966.056875, 2087.021801, 57.77580744, 
165099.0425, 20682.62962, 97764.80805), Sum.of.Total_._Cost = c(358.33, 
114310.49, 19508.2, 84655, 47154.23, 7072, 21210, 106780.34, 
17757.89), Average.of.STW_Treatment_Cost_BASIC = c(155.1394461, 
155.1394461, 155.1394461, 155.1394461, 155.1394461, 155.1394461, 
155.1394461, 155.1394461, 155.1394461), Average.of.STW_Treatment_Cost_HIGH = c(236.4912345, 
236.4912345, 236.4912345, 236.4912345, 236.4912345, 236.4912345, 
236.4912345, 236.4912345, 236.4912345), Average.of.STW_Treatment_Cost_INTENSIVE = c(1023.192673, 
1023.192673, 1023.192673, 1023.192673, 1023.192673, 1023.192673, 
1023.192673, 1023.192673, 1023.192673)), class = "data.frame", row.names = c(NA, 
-9L))
4

2 回答 2

9

我认为做一些数据准备会更容易,这样您就可以将所有框放在一个具有共享 x 轴的方面。例如,我们可以计算减少 Kg 的累积总和,并使用它来定义每个框的起始 x。

编辑 - 添加ylim = c(0, NA), xlim = c(0, NA),以将ggrepel::geom_text_repel文本保持在绘图的正范围内。

library(ggplot2)
library(ggrepel)
library(stringr) 
library(dplyr)

Cost %>%
  arrange(desc(Average.of.Cost_Per_Kg_P_Removal.undiscounted..LOW_Oncost)) %>%
  mutate(Row.Labels = forcats::fct_inorder(Row.Labels),
         cuml_reduc = cumsum(Average.of.FS_Annual_P_Reduction_Kg),
         bar_start  = cuml_reduc - Average.of.FS_Annual_P_Reduction_Kg,
         bar_center = cuml_reduc - 0.5*Average.of.FS_Annual_P_Reduction_Kg) %>%
  ggplot(aes(xmin = bar_start, xmax = cuml_reduc,
             ymin = 0, ymax = Average.of.Cost_Per_Kg_P_Removal.undiscounted..LOW_Oncost)) +
  geom_rect(fill = "grey", colour = "black") +
  geom_text_repel(aes(x = bar_center, 
                      y = Average.of.Cost_Per_Kg_P_Removal.undiscounted..LOW_Oncost,
                      label = str_wrap(Row.Labels, 15)), 
                  ylim = c(0, NA), xlim = c(0, NA),  ## EDIT
                  size = 3, nudge_y = 1E4, nudge_x = 2, lineheight = 0.7, 
                  segment.alpha = 0.3) +
  scale_y_continuous(labels = scales::comma) +
  labs(x = "Measure code and average P reduction (kg/P/yr)",
       y = "Mean annual TOTEX (£/kg) of P removal (thousands)")

在此处输入图像描述

于 2019-12-23T18:01:09.920 回答
1

您可以尝试稍微缩放这些值,例如使用对数化。由于我更喜欢​​底图,因此gglplot2我向您展示了相应的基本解决方案barplot

首先,我们将第一列转换为行名并将其删除。

cost <- `rownames<-`(Cost[-1], Cost[,1])

定义宽度barplot非常简单,因为它有一个选项width=,我们可以输入相应变量的对数值。对于条形标签,我们需要计算位置并使用text; 为了实现换行,我们可以使用strwrap. 如果遇到困难,标签可以方便地省略(如示例中的#6)。最后我们使用 (headless) arrows 。

# logarithmize values
w <- log(w1 <- cost$Average.of.Cost_Per_Kg_P_Removal.undiscounted..LOW_Oncost)
# define vector labels inside / outside, at best by hand
inside <- as.logical(c(0, 1, 0, 1, 1, 0, 1, 1, 1))
# calculate `x0` values of labels
x0 <- w / 2 + c(0, cumsum(w)[- length(w)])
# define y values o. labels
y0 <- ifelse(inside, colSums(t(cost)) / 2, 1.5e5)
# make labels using 'strwrap' 
labs <- mapply(paste, strwrap(rownames(cost), 15, simplify=F), collapse="\n")
# define nine colors
colores <- hcl.colors(9, "Spectral", alpha=.7)

# the actual plot
b <- barplot(cs <- colSums(t(cost)), width=w, space=0, ylim=c(1, 2e5), 
             xlim=c(-1, 80), xaxt="n", xaxs="i", col=colores, border=NA,
             xlab="Measure code and average P reduction (kg/P/yr)",
             ylab="Mean annual TOTEX (£/kg) of P removal (thousands)")

# place lables, leave out # 6
text(x0[-6], y0[-6], labels=labs[-6], cex=.7)
# arrows
arrows(x0[c(1, 3)], 1.35e5, x0[c(1, 3)], cs[c(1, 3)], length=0)
# label # 6
text(40, 1e5, labs[6], cex=.7)
# arrow # 6
arrows(40, 8.4e4, x0[6], cs[6], length=0)
# make x axis
axis(1, c(0, cumsum(log(seq(0, 1e5, 1e4)[-1]))), 
     labels=format(c(0, cumsum(seq(0, 1e5, 1e4)[-1])), format="d"), tck=-.02)
# put it in a box
box()

结果

在此处输入图像描述

我希望我得到了正确的 x 轴值。

您可能需要弄清楚可能的新功能是如何工作的,但是使用帮助文件非常容易,例如 type ?barplot

于 2019-12-29T14:47:21.143 回答