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

Plotly Python中多Y值按X分组渐变着色及多DataFrame绘图问题

问题描述

我有一个96行24列的DataFrame,每24行代表一天,每一列对应一小时;该数据也可拆分为4个独立的24×24的DataFrame以简化绘图。

我需要实现两个核心需求:

  • 绘制每列的全部96行数据,用颜色区分不同日期,且每个日期内按小时呈现渐变着色,以此叠加观察每日小时规律。
  • 将另外3个DataFrame的数据添加到同一图中,同时解决直接用96×24 DataFrame绘图时出现的长度不匹配错误。

目前针对单个24×24 DataFrame尝试了以下代码,但得到的是X方向渐变(同一X值的所有Y值颜色相同,随X增大颜色变化),不符合需求:

list_1 = []
for i in range(1,25,1):
    list_1.append('MTU_'+str(i))

df_w = df_w.set_axis(list_1, axis='columns')
fig = px.scatter(df_w, x=df_w.index, y=df_w.columns, color = df_w.columns ,color_continuous_scale=["red", "orange", "yellow"],
                 title="Forecast distribution for 01/01/2023")

fig.show()

解决方案

1. 单个DataFrame的正确着色(按小时渐变)

你当前代码的问题是:把color参数绑定到了列名(小时),但没有将每个数据点与对应的小时数值关联,且宽格式数据无法让Plotly识别每个点的小时属性。解决思路是先把宽格式转为长格式,让每个点携带小时数值和日期标识。

示例代码:

import pandas as pd
import plotly.express as px

# 格式化列名(如果没做的话)
df_w.columns = [f'MTU_{i}' for i in range(1,25)]

# 转长格式:拆分列到行,保留索引(日期内的行标识)、小时列名、对应值
df_long = df_w.stack().reset_index()
df_long.columns = ['date_row_id', 'hour', 'value']

# 提取小时数字(从MTU_1转为整数1),作为颜色映射依据
df_long['hour_num'] = df_long['hour'].str.extract('(\d+)').astype(int)

# 绘图:color绑定小时数值,实现同一日期内按小时渐变
fig = px.scatter(df_long, x='date_row_id', y='value', color='hour_num',
                 color_continuous_scale=["red", "orange", "yellow"],
                 title="Forecast distribution for 01/01/2023")
fig.show()

2. 多个DataFrame叠加绘图

可以通过循环遍历4个DataFrame,每个转为长格式后用Plotly Graph Objects添加轨迹,同时给每个日期设置独立的颜色方案或标记样式,方便区分。

示例代码:

import plotly.graph_objects as go

# 假设4个DataFrame存在列表dfs中,对应4天的日期标签
dfs = [df_day1, df_day2, df_day3, df_day4]
date_labels = ['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04']
# 给每个日期分配独立的渐变色板
color_scales = [["red", "orange", "yellow"], ["blue", "cyan", "lightblue"],
                ["green", "lime", "yellowgreen"], ["purple", "violet", "pink"]]

fig = go.Figure()

for idx, df in enumerate(dfs):
    # 格式化列名+转长格式
    df.columns = [f'MTU_{i}' for i in range(1,25)]
    df_long = df.stack().reset_index()
    df_long.columns = ['row_id', 'hour', 'value']
    df_long['hour_num'] = df_long['hour'].str.extract('(\d+)').astype(int)
    
    # 添加轨迹:按小时渐变,日期用图例区分
    fig.add_trace(go.Scatter(
        x=df_long['row_id'],
        y=df_long['value'],
        mode='markers',
        marker=dict(
            color=df_long['hour_num'],
            colorscale=color_scales[idx],
            # 只显示第一个颜色条,避免重复
            showscale=(idx==0)
        ),
        name=date_labels[idx]
    ))

# 统一布局设置
fig.update_layout(
    title='Daily Hourly Forecast Distribution',
    xaxis_title='Row Index',
    yaxis_title='Value',
    coloraxis_colorbar=dict(title='Hour')
)
fig.show()

3. 解决96×24 DataFrame的长度不匹配问题

直接使用96行的原始数据时,核心是先给每行标记所属的日期分组,再转长格式确保所有参数长度一致:

import plotly.express as px

# 处理96×24的原始DataFrame
df_96 = pd.DataFrame(...)  # 你的原始96行数据
df_96.columns = [f'MTU_{i}' for i in range(1,25)]

# 给每行标记日期分组:每24行一组,共4组
df_96['date'] = pd.cut(df_96.index, bins=4, labels=['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04'])

# 转长格式
df_96_long = df_96.set_index('date').stack().reset_index()
df_96_long.columns = ['date', 'hour', 'value']
df_96_long['hour_num'] = df_96_long['hour'].str.extract('(\d+)').astype(int)

# 绘图:可以选择叠加或分面展示
fig = px.scatter(df_96_long, x=df_96_long.index, y='value', color='hour_num',
                 color_continuous_scale=["red", "orange", "yellow"],
                 title='Hourly Forecast Over 4 Days',
                 # 可选:按日期分面,避免叠加过密
                 # facet_col='date'
)
fig.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 19:45:13