如何将Pandas DataFrame的values列拆分为多行X,Y值对?
Pandas DataFrame拆分XY数值对为独立行的实现方法
问题场景
现有Pandas DataFrame,其中values列存储了可变数量的逗号分隔X,Y数值对,需要将每一组X,Y拆分为单独一行,同时保留对应的tube和curve列数据。
示例数据
原DataFrame:
tube curve values 1 E88CC 0 0, 0, 25, 7, 50, 15 2 E88CC -1 0, 0, 25, 0.7, 50, 5.5, 75, 13
目标格式:
tube curve x y 0 E88CC 0 0.0 0.0 1 E88CC 0 25.0 7.0 2 E88CC 0 50.0 15.0 3 E88CC -1 0.0 0.0 4 E88CC -1 25.0 0.7 5 E88CC -1 50.0 5.5 6 E88CC -1 75.0 13.0
实现方案
方法1:遍历行构造新数据(直观易理解)
这种方法逻辑清晰,适合新手快速上手,也方便处理异常情况:
import pandas as pd # 构造示例DataFrame data = { 'tube': ['E88CC', 'E88CC'], 'curve': [0, -1], 'values': ['0, 0, 25, 7, 50, 15', '0, 0, 25, 0.7, 50, 5.5, 75, 13'] } df = pd.DataFrame(data, index=[1,2]) # 初始化空列表存储拆分后的数据 rows = [] # 遍历原DataFrame的每一行 for _, row in df.iterrows(): # 将values字符串按逗号分割并转换为浮点数值列表 vals = list(map(float, row['values'].split(', '))) # 校验数值对数量是否为偶数(避免无效数据) if len(vals) % 2 != 0: print(f"警告:行{row.name}的values元素个数为奇数,已跳过该部分数据") continue # 按每两个元素一组拆分X,Y对,并存入列表 for x, y in zip(vals[::2], vals[1::2]): rows.append({ 'tube': row['tube'], 'curve': row['curve'], 'x': x, 'y': y }) # 将列表转换为目标DataFrame result_df = pd.DataFrame(rows) print(result_df)
方法2:利用Pandas内置函数(更高效)
如果数据量较大,推荐使用Pandas的向量化操作提升效率:
import pandas as pd # 构造示例DataFrame data = { 'tube': ['E88CC', 'E88CC'], 'curve': [0, -1], 'values': ['0, 0, 25, 7, 50, 15', '0, 0, 25, 0.7, 50, 5.5, 75, 13'] } df = pd.DataFrame(data, index=[1,2]) # 1. 拆分values字符串为数值列表 df['values'] = df['values'].str.split(', ').apply(lambda x: list(map(float, x))) # 2. 将列表拆分为单行元素,同时保留分组标识 expanded_df = df.explode('values').reset_index(drop=True) expanded_df['pair_id'] = expanded_df.groupby(['tube', 'curve']).cumcount() // 2 expanded_df['coord_type'] = expanded_df.groupby(['tube', 'curve']).cumcount() % 2 # 3. 透视得到X、Y列,整理格式 result_df = expanded_df.pivot( index=['tube', 'curve', 'pair_id'], columns='coord_type', values='values' ).reset_index(drop=False) result_df.columns = ['tube', 'curve', 'pair_id', 'x', 'y'] result_df = result_df.drop('pair_id', axis=1) print(result_df)
关键说明
vals[::2]取列表中索引为偶数的元素(即所有X值),vals[1::2]取索引为奇数的元素(即所有Y值)- 方法1中的校验步骤可根据实际需求选择保留或移除
- 方法2利用
explode和groupby.cumcount实现分组内的序号标记,再通过pivot完成列转换,适合处理大规模数据
内容的提问来源于stack exchange,提问作者Andres Martinelli
相关产品推荐
相关产品推荐

