You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何将含主列与子列的Excel表格转换为Pandas DataFrame以绘制图表

如何将含主列与子列的Excel表格转换为Pandas DataFrame以绘制图表

嘿,我懂你这种烦恼——带主列(参与者编号)和子列(测试类型)的Excel表格,直接用stack()处理会把数据拆得七零八落,行数暴增不说,结构还完全不适合后续画趋势图。我来给你调整一下处理流程,保证结果刚好符合你的绘图需求:

第一步:正确读取带复合表头的Excel

你之前读数据的时候,没告诉Pandas表格有两层表头(主列是参与者,子列是测试类型),导致后续stack乱了套。我们要指定用前两行作为多级列索引:

import pandas as pd

# 读取Excel,指定前两行作为多级表头
DSAdf1 = pd.read_excel('dsa_for_clusters.xlsx', sheet_name="DSA", header=[0, 1])

这样Pandas会自动识别“参与者编号”和“测试类型”的层级关系,不会把表头当数据处理。

第二步:合并多级列名(可选,但更直观)

现在列名是多级的,比如(Participant1, TypeA),我们可以把它们合并成更易读的单一级列名,方便后续操作:

# 合并多级列名,格式为「参与者_测试类型」
DSAdf1.columns = ['_'.join(col).strip() for col in DSAdf1.columns.values]

这一步之后,列名就变成了Participant1_TypeAParticipant1_TypeB这种清晰的格式。

第三步:转换为适合绘图的长格式

melt()代替单纯的stack(),它能精准控制哪些是固定的标识符列(比如Date),哪些是需要展开的测量列(各个参与者+测试类型的组合),不会产生冗余行:

# 转换为长格式:Date作为固定列,其他列展开为「参与者_类型」和「测试值」
df_long = DSAdf1.melt(id_vars=['Date'], var_name='Participant_Type', value_name='Test_Value')

现在的DataFrame结构是:Date | Participant_Type | Test_Value,已经比你之前的结果紧凑多了。

第四步:拆分列名,方便多维度筛选绘图

如果需要单独按“参与者”或“测试类型”筛选数据绘图,我们可以把Participant_Type拆成两列:

# 拆分「参与者_类型」列,得到独立的Participant和DSA_Type列
df_long[['Participant', 'DSA_Type']] = df_long['Participant_Type'].str.split('_', expand=True)
# 删掉中间的Participant_Type列(可选)
df_long = df_long.drop('Participant_Type', axis=1)

现在你的DataFrame结构就是完美的绘图格式:Date | Test_Value | Participant | DSA_Type,每一行对应一个日期下某个参与者的某类测试值,完全没有冗余数据。

为什么这个方法比你原来的stack()更好?

你之前用stack()会把所有层级的索引都展开,包括Date列的行索引,导致大量重复的行(比如同一个Date会被重复多次)。而melt()只展开你指定的测量列,保留Date作为固定的标识符,行数和原始Excel里的有效数据行数一致,完全符合你“容易处理并绘制不同类型测试值随时间变化曲线”的需求。

比如现在你可以轻松用Seaborn画每个参与者的各类测试值趋势图:

import seaborn as sns
import matplotlib.pyplot as plt

# 按参与者分组,绘制不同类型测试值的时间趋势
sns.lineplot(data=df_long, x='Date', y='Test_Value', hue='Participant', style='DSA_Type')
plt.title('各类DSA测试值随时间变化趋势(按参与者分组)')
plt.show()

备注:内容来源于stack exchange,提问作者Ghof-90

火山引擎 最新活动