已提供必要美学属性仍遇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
相关产品推荐
相关产品推荐

