You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ggplot2绘图Y轴数值异常偏高(远超最大63%)及添加误差棒需求

问题

使用ggplot2绘制图表时遇到两个问题:

  1. Y轴显示数值高达400,但实际Cover最大值仅为63%,即使将Cover除以100,Y轴最大值变为4,仍不符合预期
  2. 需要为图表添加误差棒

数据结构

> data.frame':  720 obs. of  6 variables:
> Site    : Factor w/ 2 levels "DRP","PSP": 2 2 2 2 2 2 2 2 2 2 ...
> Plot_ID : int  1 2 3 4 5 6 7 8 9 10 ...
> Gradient: Factor w/ 3 levels "Low","Medium",..: 3 3 3 3 3 3 3 3 3 3 ...
> Sp.     : Factor w/ 4 levels "AG","FA","SN",..: 2 2 2 2 2 2 2 2 2 2 ...
> P.A     : int  1 1 1 1 1 1 1 1 1 1 ...
> Cover   : int  16 36 16 36 36 63 16 36 36 36 ...

数据表格示例

Site Plot_ID Gradient Sp. P.A Cover G2 Percentage
> 1  PSP       1     High  FA   1    16  3       0.16
> 2  PSP       2     High  FA   1    36  3       0.36
> 3  PSP       3     High  FA   1    16  3       0.16
> 4  PSP       4     High  FA   1    36  3       0.36
> 5  PSP       5     High  FA   1    36  3       0.36
> 6  PSP       6     High  FA   1    63  3       0.63

数据集样本

Site    Plot_ID Gradient    Sp. P/A Cover
PSP 1   High    FA  1   16
DRP 1   Medium  FA  0   0
PSP 1   High    AG  1   16
DRP 1   Medium  AG  0   0
PSP 1   High    SS  0   0
DRP 1   Medium  SS  0   0
PSP 1   High    SN  1   16
DRP 1   Medium  SN  0   0
PSP 2   High    FA  1   36
DRP 2   Medium  FA  0   0
PSP 2   High    AG  0   0
DRP 2   Medium  AG  1   3
PSP 2   High    SS  0   0
DRP 2   Medium  SS  0   0
PSP 2   High    SN  0   0
DRP 2   Medium  SN  0   0
PSP 3   High    FA  1   16
DRP 3   High    FA  1   1
PSP 3   High    AG  1   16
DRP 3   High    AG  1   36
PSP 3   High    SS  0   0
DRP 3   High    SS  0   0
PSP 3   High    SN  0   0
DRP 3   High    SN  0   0
PSP 4   High    FA  1   36
DRP 4   High    FA  1   16
PSP 4   High    AG  0   0
DRP 4   High    AG  1   1
PSP 4   High    SS  0   0
DRP 4   High    SS  1   16
PSP 4   High    SN  0   0
DRP 4   High    SN  1   16
PSP 5   High    FA  1   36
DRP 5   Medium  FA  0   0
PSP 5   High    AG  0   0
DRP 5   Medium  AG  0   0
PSP 5   High    SS  0   0
DRP 5   Medium  SS  0   0
PSP 5   High    SN  0   0

当前代码

ggplot(df) +
  aes(
    x = Sp.,
    fill = Gradient,
    group = Gradient,
    weight = Cover
  ) +
  geom_bar(position = "dodge") +
  scale_fill_brewer(palette = "Greys", direction = 1) +
  theme_bw() +
  facet_wrap(vars(Site))

解决方案

1. 解决Y轴数值异常问题

你的代码中使用geom_bar(weight = Cover)时,ggplot2会对每个分组下的所有Cover值求和,而不是取均值或单个值。因为每个Sp.+Gradient+Site组合对应多个Plot_ID的记录,求和后数值自然远大于单个Cover的最大值。

方法1:提前汇总数据(推荐,更灵活)

用dplyr包对数据按Site、Gradient、Sp.分组,计算平均Cover(以及后续误差棒需要的标准差):

library(dplyr)

df_summary <- df %>%
  group_by(Site, Gradient, Sp.) %>%
  summarise(
    mean_cover = mean(Cover, na.rm = TRUE),
    sd_cover = sd(Cover, na.rm = TRUE),
    .groups = "drop"
  )

用汇总后的数据绘图:

ggplot(df_summary) +
  aes(x = Sp., y = mean_cover, fill = Gradient) +
  geom_bar(stat = "identity", position = "dodge") +
  scale_fill_brewer(palette = "Greys", direction = 1) +
  theme_bw() +
  facet_wrap(vars(Site)) +
  labs(y = "Cover (%)")

方法2:直接用stat_summary绘图

无需提前汇总,直接用stat_summary计算均值并绘制柱状图:

ggplot(df) +
  aes(x = Sp., y = Cover, fill = Gradient) +
  stat_summary(fun = mean, geom = "bar", position = "dodge") +
  scale_fill_brewer(palette = "Greys", direction = 1) +
  theme_bw() +
  facet_wrap(vars(Site)) +
  labs(y = "Cover (%)")

2. 添加误差棒

误差棒通常基于标准差或标准误,以下是两种实现方式:

基于提前汇总的数据

在汇总数据基础上,用geom_errorbar添加误差棒,注意设置对齐的dodge宽度:

ggplot(df_summary) +
  aes(x = Sp., y = mean_cover, fill = Gradient, group = Gradient) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.9)) +
  geom_errorbar(
    aes(ymin = mean_cover - sd_cover, ymax = mean_cover + sd_cover),
    position = position_dodge(width = 0.9),
    width = 0.2
  ) +
  scale_fill_brewer(palette = "Greys", direction = 1) +
  theme_bw() +
  facet_wrap(vars(Site)) +
  labs(y = "Cover (%)")

直接用stat_summary添加误差棒

无需提前汇总,用stat_summary同时绘制均值和误差棒:

# 用均值±标准差
ggplot(df) +
  aes(x = Sp., y = Cover, fill = Gradient) +
  stat_summary(fun = mean, geom = "bar", position = "dodge") +
  stat_summary(
    fun.data = mean_sdl,
    geom = "errorbar",
    position = position_dodge(width = 0.9),
    width = 0.2
  ) +
  scale_fill_brewer(palette = "Greys", direction = 1) +
  theme_bw() +
  facet_wrap(vars(Site)) +
  labs(y = "Cover (%)")

如果想用标准误,可自定义计算函数:

mean_se <- function(x) {
  se <- sd(x, na.rm = TRUE)/sqrt(length(na.omit(x)))
  data.frame(y = mean(x, na.rm = TRUE), ymin = mean(x, na.rm = TRUE) - se, ymax = mean(x, na.rm = TRUE) + se)
}

ggplot(df) +
  aes(x = Sp., y = Cover, fill = Gradient) +
  stat_summary(fun = mean, geom = "bar", position = "dodge") +
  stat_summary(
    fun.data = mean_se,
    geom = "errorbar",
    position = position_dodge(width = 0.9),
    width = 0.2
  ) +
  scale_fill_brewer(palette = "Greys", direction = 1) +
  theme_bw() +
  facet_wrap(vars(Site)) +
  labs(y = "Cover (%)")

内容的提问来源于stack exchange,提问作者Fabio Giacomelli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 20:14:52