如何用Pandas实现按ID抽取3个等间隔数据点(适配不同观测次数)
问题:基于Pandas处理随访数据集的等间隔数据抽取
我有一个包含数百人的随访数据集,每人的观测次数不同(最多8次),并完成了多项测试。每个ID的Time值均为整数序列。项目目标是分析个体数据变化,需为每个ID从其所有数据中抽取3个等间隔数据点:
- 恰好3次观测的ID(如ID1):全部保留;
- 不足3次观测的ID(如ID4):排除;
- 观测次数多于3且为奇数的ID(如ID3):保留首次、末次及中间观测;
- 观测次数多于3且为偶数的ID(如ID2):保留首次、末次,中间取两个观测的平均值。
示例数据集
import pandas as pd dict_data = { "ID": [1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4], "Time": [1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5, 1, 2], "AlBa": [5, 2, 1, 8, 7, 6, 5, 9, 7, 6, 4, 2, 3, 1], "Tiri": [4, 3, 2, 10, 9, 5, 4, 5, 4, 3, 2, 1, 4, 4] } df_test = pd.DataFrame(dict_data) print(df_test)
期望输出
ID Time AlBa Tiri 0 1 1.0 5.0 4 1 1 2.0 2.0 3 2 1 3.0 1.0 2 3 2 1.0 8.0 10 4 2 2.5 6.5 7 5 2 4.0 5.0 4 6 3 1.0 9.0 5 7 3 3.0 6.0 3 8 3 5.0 2.0 1
解决方案
通过分组结合自定义函数可实现需求,具体代码如下:
import pandas as pd def process_id_group(group): n = len(group) # 排除观测次数不足3的ID if n < 3: return pd.DataFrame() # 恰好3次观测,直接返回原数据 elif n == 3: return group # 观测次数为奇数,取首次、中间、末次行 elif n % 2 == 1: mid_idx = n // 2 return group.iloc[[0, mid_idx, -1]] # 观测次数为偶数,取首次、中间两行均值、末次行 else: mid_rows = group.iloc[[n//2 -1, n//2]] mid_mean = mid_rows.mean(numeric_only=True) mid_mean['ID'] = group['ID'].iloc[0] # 合并三部分数据 result = pd.concat([group.iloc[[0]], mid_mean.to_frame().T, group.iloc[[-1]]], ignore_index=True) # 修正中间行的Time值为均值 result.loc[1, 'Time'] = mid_rows['Time'].mean() return result # 按ID分组处理数据 processed_df = df_test.groupby('ID', group_keys=False).apply(process_id_group) # 重置索引并调整列顺序 processed_df = processed_df.reset_index(drop=True)[['ID', 'Time', 'AlBa', 'Tiri']] print(processed_df)
代码说明
- 自定义分组处理函数:针对每个ID的分组,根据观测次数执行对应逻辑:
- 观测次数<3:返回空DataFrame实现自动过滤
- 观测次数=3:直接返回原分组数据
- 观测次数为奇数:通过索引提取首次、中间、末次行
- 观测次数为偶数:计算中间两行的数值均值,构造新行后合并首次、均值行、末次行
- 分组应用与后处理:用
groupby将函数应用到每个ID分组,最后重置索引并调整列顺序匹配期望输出
内容的提问来源于stack exchange,提问作者Sid0311
相关产品推荐
相关产品推荐

