如何通过Pandas将患者多小时医疗测量数据的长格式DataFrame转换为宽格式DataFrame
解决方法:将患者多小时测量数据转为单行宽格式
首先,你的思路方向是对的,但pd.concat的用法和循环逻辑出了问题,先来看正确的实现方式,再分析你的错误。
步骤1:构造示例数据
先把你给出的示例数据转换成可运行的DataFrame:
import pandas as pd # 构造示例数据 data = { 'patientid': [1, 1, 2, 2], 'hour': [1, 2, 1, 2], 'measurementx': [13.5, 13.9, 11.5, 14.9], 'measurementy': [2030, 2013, 1890, 2009] } x_binary = pd.DataFrame(data)
步骤2:实现目标格式(推荐方法)
我们可以用groupby分组后,将每个患者的所有行数据展平为一维,再组合成新的DataFrame:
# 按患者ID分组,将每组的非ID列展平为一维数组 grouped = x_binary.groupby('patientid').apply( lambda group: group.drop('patientid', axis=1).values.flatten() ) # 转换为DataFrame并重置索引 x_binary_compact = grouped.to_frame().reset_index() # 生成匹配需求的列名:重复hour、measurementx、measurementy hour_count = x_binary['hour'].nunique() new_columns = ['patientid'] + [col for _ in range(hour_count) for col in ['hour', 'measurementx', 'measurementy']] x_binary_compact.columns = new_columns # 查看结果 print(x_binary_compact)
运行后会得到你想要的格式:
patientid hour measurementx measurementy hour measurementx measurementy 0 1 1 13.5 2030 2 13.9 2013 1 2 1 11.5 1890 2 14.9 2009
另一种方法:透视表实现
如果你习惯用透视表,也可以通过给列添加小时标识,再调整列名来实现:
# 生成带小时标识的临时列 x_binary['hour_label'] = x_binary['hour'].astype(str) # 透视成宽格式 pivoted = x_binary.pivot( index='patientid', columns='hour_label', values=['hour', 'measurementx', 'measurementy'] ) # 展平多层列名,还原成重复的列名格式 pivoted.columns = [col[0] for col in pivoted.columns] # 重置索引得到最终结果 x_binary_compact = pivoted.reset_index()
分析你的代码错误
你遇到的TypeError主要有三个原因:
pd.concat用法错误:pd.concat的第一个参数必须是可迭代对象(比如列表),正确写法是pd.concat([df1, df2], axis=1),而你直接传入了x_binary_compact和row,导致参数解析混乱。- 数据类型不匹配:
itertuples返回的是元组,不是DataFrame/Series,不能直接和DataFrame拼接。 - 循环逻辑问题:你的拼接逻辑无法正确将同一患者的行合并到同一行,反而会导致数据结构混乱。
内容的提问来源于stack exchange,提问作者cercio




