用 Plotly 打造去云澜栖多维度环境数据可视化:温度、湿度、风速、海拔联动分析面板

1. 引言

去云澜栖作为高海拔生态监测站点,其环境数据涵盖温度、湿度、风速、海拔等多个维度。面对这些多源异构的时序数据,传统静态图表难以呈现维度之间的关联与联动变化。本文将基于 Plotly 构建一个交互式多维度环境数据可视化面板,实现温度、湿度、风速、海拔的联动分析,帮助研究者快速洞察环境变化规律。

2. 数据准备与预处理

2.1 模拟环境数据集

为便于演示,我们构造一份包含时间、温度、湿度、风速、海拔的模拟数据集:

python 复制代码
import pandas as pd
import numpy as np
from datetime import datetime, timedelta

# 生成 7 天、每 10 分钟一条的模拟数据
np.random.seed(42)
base_time = datetime(2025, 6, 1, 0, 0, 0)
time_list = [base_time + timedelta(minutes=10 * i) for i in range(7 * 24 * 6)]

# 海拔随地形起伏(模拟 1200m - 1800m 之间变化)
altitude = 1200 + 300 * np.sin(np.linspace(0, 4 * np.pi, len(time_list))) + np.random.normal(0, 5, len(time_list))

# 温度随海拔升高而降低,并叠加昼夜波动
temperature = 28 - (altitude - 1200) * 0.006 + 5 * np.sin(np.linspace(0, 14 * np.pi, len(time_list))) + np.random.normal(0, 0.8, len(time_list))

# 湿度与温度负相关,并叠加随机扰动
humidity = 70 - (temperature - 20) * 1.2 + np.random.normal(0, 5, len(time_list))
humidity = np.clip(humidity, 20, 100)

# 风速随海拔升高而增大,并叠加阵风扰动
wind_speed = 2 + (altitude - 1200) * 0.004 + 3 * np.abs(np.sin(np.linspace(0, 8 * np.pi, len(time_list)))) + np.random.normal(0, 0.5, len(time_list))
wind_speed = np.clip(wind_speed, 0, 20)

df = pd.DataFrame({
    "时间": time_list,
    "温度(℃)": temperature.round(2),
    "湿度(%)": humidity.round(2),
    "风速(m/s)": wind_speed.round(2),
    "海拔(m)": altitude.round(2)
})
df.head()

2.2 数据清洗与重采样

python 复制代码
# 检查缺失值
print(df.isnull().sum())

# 按小时重采样,便于面板展示
df["时间"] = pd.to_datetime(df["时间"])
df_hourly = df.set_index("时间").resample("1H").mean().reset_index()
df_hourly.head()

3. 构建联动分析面板

3.1 创建子图布局

使用 make_subplots 创建 2×2 的子图网格,分别展示温度、湿度、风速、海拔的时序曲线:

python 复制代码
import plotly.graph_objects as go
from plotly.subplots import make_subplots

fig = make_subplots(
    rows=2, cols=2,
    subplot_titles=("温度变化", "湿度变化", "风速变化", "海拔变化"),
    shared_xaxes=True,
    vertical_spacing=0.08,
    horizontal_spacing=0.1
)

# 温度曲线
fig.add_trace(go.Scatter(
    x=df_hourly["时间"], y=df_hourly["温度(℃)"],
    name="温度", line=dict(color="#FF6B6B", width=2),
    hovertemplate="时间: %{x|%Y-%m-%d %H:%M}<br>温度: %{y:.2f}℃<extra></extra>"
), row=1, col=1)

# 湿度曲线
fig.add_trace(go.Scatter(
    x=df_hourly["时间"], y=df_hourly["湿度(%)"],
    name="湿度", line=dict(color="#4ECDC4", width=2),
    hovertemplate="时间: %{x|%Y-%m-%d %H:%M}<br>湿度: %{y:.2f}%<extra></extra>"
), row=1, col=2)

# 风速曲线
fig.add_trace(go.Scatter(
    x=df_hourly["时间"], y=df_hourly["风速(m/s)"],
    name="风速", line=dict(color="#45B7D1", width=2),
    hovertemplate="时间: %{x|%Y-%m-%d %H:%M}<br>风速: %{y:.2f} m/s<extra></extra>"
), row=2, col=1)

# 海拔曲线
fig.add_trace(go.Scatter(
    x=df_hourly["时间"], y=df_hourly["海拔(m)"],
    name="海拔", line=dict(color="#96CEB4", width=2),
    hovertemplate="时间: %{x|%Y-%m-%d %H:%M}<br>海拔: %{y:.2f} m<extra></extra>"
), row=2, col=2)

fig.update_layout(
    title="去云澜栖多维度环境数据联动分析面板",
    height=800,
    hovermode="x unified",
    showlegend=False,
    template="plotly_white"
)
fig.show()

3.2 添加联动十字线

通过 fig.update_layout 的 hovermode="x unified" 实现四个子图共享 X 轴悬停,鼠标移动时同步显示同一时刻的四项指标:

python 复制代码
fig.update_layout(
    hovermode="x unified",
    hoverlabel=dict(bgcolor="white", font_size=12)
)

4. 维度关联分析

4.1 温度与海拔散点图

python 复制代码
fig_scatter = go.Figure()

fig_scatter.add_trace(go.Scatter(
    x=df_hourly["海拔(m)"], y=df_hourly["温度(℃)"],
    mode="markers",
    marker=dict(
        size=df_hourly["湿度(%)"] / 3,
        color=df_hourly["风速(m/s)"],
        colorscale="Viridis",
        showscale=True,
        colorbar=dict(title="风速(m/s)")
    ),
    text=df_hourly["时间"].dt.strftime("%Y-%m-%d %H:%M"),
    hovertemplate="海拔: %{x:.0f} m<br>温度: %{y:.2f}℃<br>湿度: %{marker.size:.1f}%<br>风速: %{marker.color:.2f} m/s<extra></extra>"
))

fig_scatter.update_layout(
    title="温度-海拔关联(气泡大小=湿度,颜色=风速)",
    xaxis_title="海拔 (m)",
    yaxis_title="温度 (℃)",
    template="plotly_white",
    height=500
)
fig_scatter.show()

4.2 平行坐标图

平行坐标图可同时呈现四个维度的完整数据分布:

python 复制代码
fig_parcoords = go.Figure(go.Parcoords(
    line=dict(
        color=df_hourly["温度(℃)"],
        colorscale="RdYlBu_r",
        showscale=True,
        colorbar=dict(title="温度(℃)")
    ),
    dimensions=[
        dict(label="时间", values=df_hourly["时间"].astype("int64") // 10**9, range=[df_hourly["时间"].astype("int64").min() // 10**9, df_hourly["时间"].astype("int64").max() // 10**9]),
        dict(label="温度(℃)", values=df_hourly["温度(℃)"]),
        dict(label="湿度(%)", values=df_hourly["湿度(%)"]),
        dict(label="风速(m/s)", values=df_hourly["风速(m/s)"]),
        dict(label="海拔(m)", values=df_hourly["海拔(m)"])
    ]
))

fig_parcoords.update_layout(
    title="去云澜栖环境数据平行坐标图",
    height=600,
    template="plotly_white"
)
fig_parcoords.show()

5. 面板交互优化

5.1 添加范围滑块与缩放

python 复制代码
fig.update_layout(
    xaxis=dict(rangeslider=dict(visible=True), type="date"),
    xaxis2=dict(rangeslider=dict(visible=True), type="date"),
    xaxis3=dict(rangeslider=dict(visible=True), type="date"),
    xaxis4=dict(rangeslider=dict(visible=True), type="date")
)

5.2 添加维度切换按钮

python 复制代码
fig.update_layout(
    updatemenus=[
        dict(
            type="buttons",
            direction="left",
            buttons=[
                dict(label="全部显示", method="update",
                     args=[{"visible": [True, True, True, True]}]),
                dict(label="仅温度/湿度", method="update",
                     args=[{"visible": [True, True, False, False]}]),
                dict(label="仅风速/海拔", method="update",
                     args=[{"visible": [False, False, True, True]}])
            ],
            pad=dict(r=10, t=10),
            showactive=True,
            x=0.1, xanchor="left",
            y=1.15, yanchor="top"
        )
    ]
)

6. 完整面板代码

将以上模块整合为可直接运行的完整脚本:

python 复制代码
import pandas as pd
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from datetime import datetime, timedelta

# ---------- 数据生成 ----------
np.random.seed(42)
base_time = datetime(2025, 6, 1, 0, 0, 0)
time_list = [base_time + timedelta(minutes=10 * i) for i in range(7 * 24 * 6)]

altitude = 1200 + 300 * np.sin(np.linspace(0, 4 * np.pi, len(time_list))) + np.random.normal(0, 5, len(time_list))
temperature = 28 - (altitude - 1200) * 0.006 + 5 * np.sin(np.linspace(0, 14 * np.pi, len(time_list))) + np.random.normal(0, 0.8, len(time_list))
humidity = np.clip(70 - (temperature - 20) * 1.2 + np.random.normal(0, 5, len(time_list)), 20, 100)
wind_speed = np.clip(2 + (altitude - 1200) * 0.004 + 3 * np.abs(np.sin(np.linspace(0, 8 * np.pi, len(time_list)))) + np.random.normal(0, 0.5, len(time_list)), 0, 20)

df = pd.DataFrame({
    "时间": time_list,
    "温度(℃)": temperature.round(2),
    "湿度(%)": humidity.round(2),
    "风速(m/s)": wind_speed.round(2),
    "海拔(m)": altitude.round(2)
})
df["时间"] = pd.to_datetime(df["时间"])
df_hourly = df.set_index("时间").resample("1H").mean().reset_index()

# ---------- 联动面板 ----------
fig = make_subplots(
    rows=2, cols=2,
    subplot_titles=("温度变化", "湿度变化", "风速变化", "海拔变化"),
    shared_xaxes=True,
    vertical_spacing=0.08,
    horizontal_spacing=0.1
)

traces = [
    (df_hourly["温度(℃)"], "温度", "#FF6B6B", "℃", 1, 1),
    (df_hourly["湿度(%)"], "湿度", "#4ECDC4", "%", 1, 2),
    (df_hourly["风速(m/s)"], "风速", "#45B7D1", " m/s", 2, 1),
    (df_hourly["海拔(m)"], "海拔", "#96CEB4", " m", 2, 2)
]

for y, name, color, unit, row, col in traces:
    fig.add_trace(go.Scatter(
        x=df_hourly["时间"], y=y, name=name,
        line=dict(color=color, width=2),
        hovertemplate=f"时间: %{{x|%Y-%m-%d %H:%M}}<br>{name}: %{{y:.2f}}{unit}<extra></extra>"
    ), row=row, col=col)

fig.update_layout(
    title="去云澜栖多维度环境数据联动分析面板",
    height=800,
    hovermode="x unified",
    showlegend=False,
    template="plotly_white",
    updatemenus=[
        dict(
            type="buttons", direction="left",
            buttons=[
                dict(label="全部显示", method="update", args=[{"visible": [True, True, True, True]}]),
                dict(label="仅温度/湿度", method="update", args=[{"visible": [True, True, False, False]}]),
                dict(label="仅风速/海拔", method="update", args=[{"visible": [False, False, True, True]}])
            ],
            pad=dict(r=10, t=10), showactive=True,
            x=0.1, xanchor="left", y=1.15, yanchor="top"
        )
    ]
)

fig.show()

7. 总结

本文基于 Plotly 构建了去云澜栖多维度环境数据联动分析面板,实现了:

  • 四维时序联动:温度、湿度、风速、海拔在共享时间轴下同步悬停展示;
  • 维度关联挖掘:通过散点图气泡大小与颜色映射,直观呈现海拔-温度-湿度-风速的耦合关系;
  • 交互式探索:范围滑块、维度切换按钮、平行坐标图等多重交互手段,提升数据分析效率。

读者可在此基础上接入真实传感器数据流,并结合 Dash 将面板部署为 Web 服务,实现环境监测的实时可视化。

相关推荐
瓶瓶持续学习中9 小时前
数字孪生数据模型如何连接空间智能与仿真
人工智能·信息可视化
科创致远14 小时前
第一代 e+SOP 盒子配显示器实测:物美价廉的产线可视化方案
大数据·网络·人工智能·信息可视化·计算机外设·制造·精益工程
灰山君1 天前
从三维数字孪生到交互式图表:山海鲸可视化与pyecharts应用解析
大数据·信息可视化·数据分析·数字孪生·3d模型
总要学点什么3 天前
第65篇:地图卷帘控件——点「关闭卷帘」,消失的却是右边那半张地图
信息可视化·gis·webgl·cesium·空间分析
程序员清风3 天前
Python 数据可视化入门:Matplotlib 核心用法
python·信息可视化·matplotlib
科创致远3 天前
科创致远 ESD 静电监控全景落地指南
人工智能·信息可视化·制造·精益工程
2603_965148114 天前
电商选品调研:通过关键词搜索API获取市场热销商品,结合商品详情API分析竞品卖点与定价
开发语言·数据库·人工智能·python·信息可视化
迪康Defender4 天前
终端安全运维:浅谈迪康端点安全一体化管理系统工具箱实用能力
运维·安全·信息可视化·自动化·运维开发·学习方法·远程工作
数字新视界5 天前
空调双机切换器AIRC1000红外控制原理解析
大数据·物联网·信息可视化·信息与通信·一体化机柜