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

R语言绘制月度气温3D图展示年月维度气温趋势实现方法咨询

R语言同画布绘制多层3D月度气温分布图实现方法

核心思路是用分层透明度控制避免3D图常见的元素遮挡、信息杂乱问题,同时保留原始观测分布和长期变化趋势,坐标轴严格按需求设置:x轴为月份、y轴为年份、z轴为逐小时气温观测值。

前置依赖与数据预处理

先安装并加载用到的包,把数据整理成绘图需要的格式,注意提前把你用到的气温数据集存到本地R工作目录,不要直接读取在线链接避免读取失败。

# 首次运行先安装缺失包
# install.packages(c("readxl", "plotly", "data.table", "dplyr", "reshape2"))
library(readxl)
library(plotly)
library(data.table)
library(dplyr)
library(reshape2)

# 读取本地气温数据,替换成你本地的文件名即可
dt <- read_excel("temp_data.xlsx") |> as.data.table()
# 校验数据需包含三个核心字段:month(1-12数值型)、year(数值型)、hour_temp(逐小时气温数值型)
# 提前聚合计算分位数,作为分层绘制的基准:避免全量逐小时数据糊成一团
dt_agg <- dt[, .(
  q10 = quantile(hour_temp, 0.1, na.rm = T), # 10%分位低温边界
  q50 = quantile(hour_temp, 0.5, na.rm = T), # 中位气温,核心趋势层
  q90 = quantile(hour_temp, 0.9, na.rm = T)  # 90%分位高温边界
), by = .(month, year)]

多层3D图绘制代码

分层逻辑从下到上依次排布,通过透明度差突出核心趋势:

  • 最底层:月份-年份平面的填充等高线,用颜色映射中位气温,作为趋势参考底座
  • 上下边界层:10%、90%分位数气温曲面,设置极低透明度,展示逐小时气温的波动区间,不遮挡核心层
  • 核心趋势层:中位气温曲面,设置中等透明度,是展示年际、季节气温变化的核心载体
  • 最上层:10%抽样的逐小时原始观测散点,小尺寸、低透明度,保留原始数据分布特征
# 生成宽表格式适配3D曲面入参
z_q10 <- acast(dt_agg, year ~ month, value.var = "q10")
z_q50 <- acast(dt_agg, year ~ month, value.var = "q50")
z_q90 <- acast(dt_agg, year ~ month, value.var = "q90")
x_axis <- sort(unique(dt_agg$month))
y_axis <- sort(unique(dt_agg$year))

plot_ly() |>
  # 1. 底层平面等高线
  add_contour(
    data = dt_agg,
    x = ~month, y = ~year, z = ~q50,
    colors = "YlOrRd",
    showscale = F,
    contours = list(showlabels = T, labelfont = list(size = 10))
  ) |>
  # 2. 低温边界层
  add_surface(
    x = x_axis, y = y_axis, z = z_q10,
    opacity = 0.15,
    colorscale = list(c(0,1), c("#c6dbef", "#c6dbef")),
    showscale = F,
    name = "10%分位低温边界",
    hoverinfo = "name"
  ) |>
  # 3. 核心中位气温趋势层
  add_surface(
    x = x_axis, y = y_axis, z = z_q50,
    opacity = 0.6,
    colors = "YlOrRd",
    colorbar = list(title = "中位气温(℃)"),
    name = "中位气温趋势"
  ) |>
  # 4. 高温边界层
  add_surface(
    x = x_axis, y = y_axis, z = z_q90,
    opacity = 0.15,
    colorscale = list(c(0,1), c("#fcbba1", "#fcbba1")),
    showscale = F,
    name = "90%分位高温边界",
    hoverinfo = "name"
  ) |>
  # 5. 抽样原始观测点
  add_markers(
    data = dt[sample(.N, round(.N*0.1))], # 只抽10%样本避免过密
    x = ~month, y = ~year, z = ~hour_temp,
    size = I(2),
    opacity = 0.25,
    color = ~hour_temp,
    colors = "YlOrRd",
    showlegend = F,
    hoverinfo = "x+y+z"
  ) |>
  # 坐标轴与视角配置
  layout(
    scene = list(
      xaxis = list(title = "月份", dtick = 1, range = c(1,12)),
      yaxis = list(title = "年份"),
      zaxis = list(title = "逐小时气温(℃)"),
      # 调整视角减少层之间的遮挡
      camera = list(eye = list(x = 1.7, y = 1.7, z = 1.1))
    ),
    legend = list(orientation = "h", y = 1)
  )

效果优化提示

  • 如果只需要看长期趋势,可以直接隐藏上下两个分位边界层,只保留等高线底座+中位趋势面+少量散点,趋势会更清晰
  • 要突出年际变暖趋势,可以额外叠加一层线性拟合的趋势基准面,和实际中位气温面的高度差就是对应时段的气温变化幅度
  • 不要直接绘制全量逐小时气温的3D散点,高密度点会完全糊成色块,无法识别任何趋势规律

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 19:21:27