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

已提供必要美学属性仍遇geom_density_ridges缺失美学错误?

山脊线图绘制问题及替代可视化方案

问题背景

我想制作山脊线图对比月度温度数据分布:每个月有从某点向外100m间隔的20个区域的温度数据,目标是展示月度间、以及随距离向外扩展的温度变化,后续还要对比偏度、峰度等统计特征。

数据结构

当前使用的tibble数据结构如下(部分字段暂未使用):

> str(lst_c1_l1_T1)
tibble [240 × 7] (S3: tbl_df/tbl/data.frame)
 $ buffer    : Factor w/ 20 levels "100","200","300",..: 2 3 4 5 6 7 8 9 10 11 ...
 $ date      : Date[1:240], format: "2017-01-16" "2017-01-16" "2017-01-16" "2017-01-16" ...
 $ variable  : Factor w/ 40 levels "lst_c1_l1_kurtosis",..: 2 2 2 2 2 2 2 2 2 2 ...
 $ value     : num [1:240] 43.8 43.8 43.8 43.7 43.4 ...
 $ Year      : chr [1:240] "2017" "2017" "2017" "2017" ...
 $ Month     : Factor w/ 12 levels "01","02","03",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ TimePeriod: Factor w/ 2 levels "1","2": 1 1 1 1 1 1 1 1 1 1 ...

数据前6行的dput输出:

structure(list(buffer = structure(2:7, levels = c("100", "200", 
"300", "400", "500", "600", "700", "800", "900", "1000", "1100", 
"1200", "1300", "1400", "1500", "1600", "1700", "1800", "1900", 
"2000"), class = "factor"), date = structure(c(17182, 17182, 
17182, 17182, 17182, 17182), class = "Date"), variable = structure(c(2L, 
2L, 2L, 2L, 2L, 2L), levels = c("lst_c1_l1_kurtosis", "lst_c1_l1_lst", 
"lst_c1_l1_max", "lst_c1_l1_median", "lst_c1_l1_min", "lst_c1_l1_single_kurtosis", 
"lst_c1_l1_single_lst", "lst_c1_l1_single_max", "lst_c1_l1_single_median", 
"lst_c1_l1_single_min", "lst_c1_l1_single_skew", "lst_c1_l1_single_stdDev", 
"lst_c1_l1_single_variance", "lst_c1_l1_skew", "lst_c1_l1_stdDev", 
"lst_c1_l1_variance", "lst_c2_l1_kurtosis", "lst_c2_l1_lst", 
"lst_c2_l1_max", "lst_c2_l1_median", "lst_c2_l1_min", "lst_c2_l1_single_kurtosis", 
"lst_c2_l1_single_lst", "lst_c2_l1_single_max", "lst_c2_l1_single_median", 
"lst_c2_l1_single_min", "lst_c2_l1_single_skew", "lst_c2_l1_single_stdDev", 
"lst_c2_l1_single_variance", "lst_c2_l1_skew", "lst_c2_l1_stdDev", 
"lst_c2_l1_variance", "lst_c2_l2_kurtosis", "lst_c2_l2_lst", 
"lst_c2_l2_max", "lst_c2_l2_median", "lst_c2_l2_min", "lst_c2_l2_skew", 
"lst_c2_l2_stdDev", "lst_c2_l2_variance"), class = "factor"), 
    value = c(43.8048763014736, 43.7770632839523, 43.7671539457081, 
    43.6734275952591, 43.4396932500121, 43.4661731747384), Year = c("2017", 
    "2017", "2017", "2017", "2017", "2017"), Month = structure(c(1L, 
    1L, 1L, 1L, 1L, 1L), levels = c("01", "02", "03", "04", "05", 
    "06", "07", "08", "09", "10", "11", "12"), class = "factor"), 
    TimePeriod = structure(c(1L, 1L, 1L, 1L, 1L, 1L), levels = c("1", 
    "2"), class = "factor")), row.names = c(NA, -6L), class = c("tbl_df", 
"tbl", "data.frame"))

首次尝试代码及错误

我用以下代码绘制山脊线图(后续计划添加其他系列):

plot <- ggplot() +
  geom_density_ridges(lst_c1_l1_T1, mapping=aes(x = buffer, y = Month, group = Month, fill = Month, height = value))
plot

运行后出现错误:

>   plot                   
Picking joint bandwidth of 2.84
Error in `geom_density_ridges()`:
! Problem while setting up geom.
ℹ Error occurred in the 1st layer.
Caused by error in `compute_geom_1()`:
! `geom_density_ridges()` requires the following missing aesthetics: height
Run `rlang::last_trace()` to see where the error occurred.
Warning message:
The following aesthetics were dropped during statistical transformation: height
ℹ This can happen when ggplot fails to infer the correct grouping structure in the data.
ℹ Did you forget to specify a `group` aesthetic or to convert a numerical variable into a factor?

我不理解为什么已经指定的数值型height会被丢弃,group设置也没生效,参考相似问题的解决方案没用。同时也想找对比数据分布的替代方法(试过小提琴图、点图都没成功)。

二次尝试(geom_ridgeline)

改用geom_ridgeline的代码:

plot <- ggplot() +
  geom_ridgeline(lst_c1_l1_T1, mapping=aes(x=Month, y=buffer, height=value, group=buffer, scale=0.02))
plot

生成的图形不符合需求,叠加其他系列后无法对比数据生成方法的细微差异。


解决方案

1. 修正山脊线图绘制逻辑

geom_density_ridges是用来绘制密度分布的山脊线,它会自动计算密度作为height,所以你手动传入的height会被统计变换覆盖,这就是报错的原因。如果你想直接用现有value作为高度绘制山脊线,应该用geom_ridgeline,调整变量映射符合你的需求:

你的需求是每个月对应一条山脊线,x轴是buffer(距离),y轴是月份,height是温度value。正确的代码如下:

library(ggplot2)
library(ggridges)

# 将buffer转为数值型,方便x轴连续展示
lst_c1_l1_T1$buffer_num <- as.numeric(as.character(lst_c1_l1_T1$buffer))

ggplot(lst_c1_l1_T1, aes(x = buffer_num, y = Month, height = value, group = Month)) +
  geom_ridgeline(fill = "lightblue", scale = 0.5) +
  labs(x = "距离(m)", y = "月份", title = "月度温度随距离变化山脊线图") +
  theme_minimal()

这样每个月对应一条线,x轴是距离,高度是温度,能直观看到每个月温度随距离的变化趋势,以及月度间的对比。

2. 替代可视化方案

如果山脊线图达不到预期,推荐以下几种方法:

  • 折线图(带置信区间):如果后续有重复数据,可以绘制月度平均温度随距离的折线,加上置信区间展示分布:
ggplot(lst_c1_l1_T1, aes(x = buffer_num, y = value, color = Month)) +
  geom_line(stat = "summary", fun = "mean") +
  geom_ribbon(stat = "summary", fun.data = "mean_se", alpha = 0.2, aes(fill = Month)) +
  labs(x = "距离(m)", y = "温度", title = "月度温度随距离变化趋势") +
  theme_minimal()
  • 热力图:展示月份×距离的温度矩阵,用颜色直观呈现温度变化:
ggplot(lst_c1_l1_T1, aes(x = buffer_num, y = Month, fill = value)) +
  geom_tile() +
  scale_fill_viridis_c(option = "plasma") +
  labs(x = "距离(m)", y = "月份", fill = "温度", title = "温度随月份和距离变化热力图") +
  theme_minimal()
  • 箱线图/小提琴图:按月份分组,展示每个月不同距离下的温度分布(如果每个距离有多个数据点):
# 箱线图
ggplot(lst_c1_l1_T1, aes(x = Month, y = value)) +
  geom_boxplot(aes(fill = Month)) +
  labs(x = "月份", y = "温度", title = "月度温度分布箱线图") +
  theme_minimal()

# 结合距离维度的分面小提琴图
ggplot(lst_c1_l1_T1, aes(x = Month, y = value)) +
  geom_violin(aes(fill = Month)) +
  facet_wrap(~buffer) +
  labs(x = "月份", y = "温度", title = "不同距离下月度温度分布小提琴图") +
  theme_minimal()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 07:15:10