如何在ggplot2中为同一变量添加带不同单位的第二个图例?
实现双单位气温图例的方法
当然可行啦!不过比起单独加第二个图例,在同一个色条上同时显示开尔文和摄氏度数值会更直观,也不会让图表显得杂乱。下面给你调整后的代码,我会把细节说清楚:
推荐方案:单图例双单位显示
先修正你原代码里的小语法错误(多了一个右括号),然后通过自定义刻度标签实现双单位:
library(ggplot2) library(cptcity) library(raster) # 别忘了加载raster包,不然brick和rasterToPoints会报错 # 修正括号错误,读取并处理nc数据 nc <- rotate(brick(x = "fnl_20111128_00_00.nc", var = "TMP_1000mb")) df <- as.data.frame(rasterToPoints(nc)) ggplot() + geom_raster(data = df, aes(x = x, y = y, fill = X1322438400), interpolate = TRUE) + scale_fill_gradientn( colours = cpt("ncl_precip2_17lev"), name = "Temperature", # 把图例名改成更通用的 na.value = "white", # 核心:自定义刻度标签,同时显示K和℃ labels = function(k_values) { celsius_values <- round(k_values - 273.15, 1) # K转℃,保留1位小数 paste0(k_values, "K\n(", celsius_values, "℃)") # 换行显示两个单位 }, # 可选:手动指定刻度间隔,避免标签太拥挤 breaks = seq(floor(min(df$X1322438400)), ceiling(max(df$X1322438400)), by = 5) ) + theme_minimal() # 可选,让图表风格更清爽
关键说明:
- 我们通过
labels参数传入一个自定义函数,把每个开尔文数值转换成摄氏度,再用paste0把两个单位的数值换行拼接,这样色条上的每个刻度都会同时标注两种单位。 - 如果原始数据的温度范围跨度大,调整
breaks的by值可以让刻度标签更清晰。
备选方案:两个独立图例(不推荐)
如果你确实需要两个分开的图例,也可以通过添加虚拟图层实现,但这种方式会让图表冗余,容易让读者混淆,所以只作为备选:
library(ggplot2) library(cptcity) library(raster) nc <- rotate(brick(x = "fnl_20111128_00_00.nc", var = "TMP_1000mb")) df <- as.data.frame(rasterToPoints(nc)) # 提前计算摄氏度列 df$celsius <- df$X1322438400 - 273.15 ggplot() + # 主图层:开尔文温度的栅格图 geom_raster(data = df, aes(x = x, y = y, fill = X1322438400), interpolate = TRUE) + # 虚拟图层:映射摄氏度,用来生成第二个图例(不显示实际图形) geom_blank(data = df, aes(x = x, y = y, color = celsius)) + # 开尔文的颜色刻度 scale_fill_gradientn( colours = cpt("ncl_precip2_17lev"), name = "T (K)", na.value = "white" ) + # 摄氏度的颜色刻度,和开尔文用同一套色卡 scale_color_gradientn( colours = cpt("ncl_precip2_17lev"), name = "T (℃)", na.value = NA, # 隐藏缺失值的颜色 labels = function(c) round(c, 1) ) + theme(legend.position = "right") # 把两个图例放在右侧
注意:
两个图例本质对应同一个颜色映射,只是单位不同,所以实际使用中还是第一种方案更合理哦。
内容的提问来源于stack exchange,提问作者Amanda Rehbein
相关产品推荐
相关产品推荐

