如何用Pandas按每119行提取DataFrame指定列构建新DataFrame
问题描述
现有一个带datetime索引的DataFrame data,结构如下(共279817行5列):
id activity x y z datetime 1970-01-01 00:42:00.219142823 1623 A -0.152512 -8.585220 -1.219192 1970-01-01 00:42:00.269496827 1623 A 0.999466 -8.196548 -0.758926 1970-01-01 00:42:00.319850830 1623 A 0.450241 -8.701187 -1.290024 1970-01-01 00:42:00.370204834 1623 A -0.042175 -9.739563 -1.787415 1970-01-01 00:42:00.420558838 1623 A 3.551483 -10.745132 -1.266403 ... ... ... ... ... ... 1970-01-22 01:26:29.872699000 1644 A 2.239343 -8.408914 2.074087 1970-01-22 01:26:29.892898000 1644 A 2.548301 -8.157437 1.820215 1970-01-22 01:26:29.912994000 1644 A 2.636917 -7.786209 2.057322 1970-01-22 01:26:29.933195000 1644 A 2.545906 -7.743098 1.801055 1970-01-22 01:26:29.953291000 1644 A 2.373464 -8.071217 1.585503 279817 rows × 5 columns
需求:每119行提取一次x、y、z列的所有值以及对应的activity标签,将每组数据按「x列值|y列值|z列值|activity」的格式合并为新DataFrame的一行,循环处理所有数据。
可行解决思路
方法1:分组聚合(高效优先)
利用groupby批量处理,避免手动循环,适合大数量级数据:
- 生成分组键:通过行号给每119行分配同一个组编号,用
np.arange(len(data)) // 119实现(原索引为datetime,无法直接整除,需用行序号分组) - 定义聚合逻辑:对每组数据,按要求拼接每行的
x、y、z和activity;若每组内activity标签一致,直接取组内第一个值即可,不一致则按需调整 - 生成新DataFrame:将聚合结果转为结构化DataFrame
示例代码:
import numpy as np import pandas as pd # 创建分组键,每119行为一组 group_keys = np.arange(len(data)) // 119 # 定义拼接函数 def format_group(group): # 假设每组activity一致,取第一个值;若不一致可改为'|'.join(group['activity'].unique()) activity = group['activity'].iloc[0] # 按格式拼接每行数据 row_strings = [f"{x}|{y}|{z}|{activity}" for x, y, z in zip(group['x'], group['y'], group['z'])] # 将组内所有拼接结果合并为一行(用换行分隔,可按需替换为其他分隔符) return '\n'.join(row_strings) # 分组聚合得到新DataFrame new_df = data.groupby(group_keys).apply(format_group).reset_index(name='combined_data')
方法2:手动循环切片(直观可控)
如果需要精细化控制流程,可采用循环逐段处理:
- 计算总组数:用
(len(data) + 118) // 119向上取整,确保最后不足119行的部分也被处理 - 循环处理每组:逐段切片取119行数据,拼接每行的指定字段,将整组拼接结果存入列表
- 转换为DataFrame:将列表转为结构化DataFrame
示例代码:
import pandas as pd combined_rows = [] total_groups = (len(data) + 118) // 119 for i in range(total_groups): start_idx = i * 119 end_idx = start_idx + 119 group_data = data.iloc[start_idx:end_idx] # 取组内第一个activity(若不一致需调整) activity = group_data['activity'].iloc[0] # 拼接每行数据 group_strings = [f"{row['x']}|{row['y']}|{row['z']}|{activity}" for _, row in group_data.iterrows()] combined_rows.append('\n'.join(group_strings)) # 生成新DataFrame new_df = pd.DataFrame({'combined_data': combined_rows})
注意事项
- 若每组内
activity标签不一致,需明确处理逻辑:是保留每行自身的activity(即拼接时用当前行的activity),还是统一用组内某一个值 - 处理27万行数据时,
groupby方法效率远高于手动循环,优先推荐 - 如需控制数值精度,可在拼接时指定小数位数,例如
f"{row['x']:.6f}|{row['y']:.6f}|..."
内容的提问来源于stack exchange,提问作者Nickkouts
相关产品推荐
相关产品推荐

