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
相关产品推荐
相关产品推荐

