在DataFrame中剔除超出比值阈值范围的粒子数据
问题描述
初始数据:

原始代码:
import pandas as pd import numpy as np d = {'RedVal':[1,1.1,2,1.5,1.7,2,1,1.1,2,1,1.1,2,2.6,2.5,2.4,2.5], 'GreenVal':[1,1.1,1.1,1,1.1,1.7,1,1.1,1.5,1,1.9,3,2.8,2.7,2.6,2.5], 'Frame':[0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3], 'Particle':[0,0,0,0,2,2,2,2,3,3,3,3,4,4,4,4] } testframe = pd.DataFrame(data=d) framenot = 2 #set how many frames you would like to get initial ratio for ratarray = [] #initialize blank ratio array testframe.sort_values(by =[ 'Particle', 'Frame']) for particle in range(0,5): if(testframe['Particle']== particle).any() == False: particle = particle + 1 else: newframe = testframe.loc[(testframe['Frame']<= framenot) & (testframe['Particle'] == particle)] for i in range(framenot): GVal = newframe['GreenVal'].values[i] RVal = newframe['RedVal'].values[i] ratio = RVal/GVal ratarray.append(ratio) i+=1 particle+=1 ratarray = np.array(ratarray) avgRatios = np.average(ratarray.reshape(-1,framenot), axis = 1) stdRatios = np.std(ratarray.reshape(-1,framenot), axis = 1) print(avgRatios) #array with average ratios over set frames starting from initial particle print(stdRatios)
目前上述代码可计算每个粒子在Frame 0和1的RedVal/GreenVal比值的平均值(avgRatios)与标准差(stdRatios)。现需将该平均比值与后续x帧的比值进行对比,剔除后续帧比值超出“平均值±2倍标准差”范围的粒子,求实现方法。
实现方案
步骤说明
- 为每个粒子的所有帧计算RedVal/GreenVal比值,新增列到DataFrame
- 用分组计算替代原循环,高效获取每个粒子初始帧(Frame0-1)的平均比值和标准差
- 定义后续帧范围(示例为Frame≥2,可按需调整x值)
- 检查每个粒子的后续帧比值是否全部在允许区间内,筛选符合条件的粒子
代码实现
import pandas as pd import numpy as np # 1. 构建数据并计算所有帧的比值 d = {'RedVal':[1,1.1,2,1.5,1.7,2,1,1.1,2,1,1.1,2,2.6,2.5,2.4,2.5], 'GreenVal':[1,1.1,1.1,1,1.1,1.7,1,1.1,1.5,1,1.9,3,2.8,2.7,2.6,2.5], 'Frame':[0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3], 'Particle':[0,0,0,0,2,2,2,2,3,3,3,3,4,4,4,4] } testframe = pd.DataFrame(data=d) testframe['Ratio'] = testframe['RedVal'] / testframe['GreenVal'] # 新增比值列 # 2. 分组计算每个粒子初始帧的平均和标准差 framenot = 2 # 初始帧范围:Frame < framenot(即0和1) init_stats = testframe[testframe['Frame'] < framenot].groupby('Particle').agg( AvgRatio=('Ratio', 'mean'), StdRatio=('Ratio', 'std') ).reset_index() # 3. 定义后续帧范围(示例:Frame >=2,可替换为Frame >= framenot到Frame <= framenot+x) x_frames = testframe[testframe['Frame'] >= framenot] # 4. 合并初始统计和后续帧数据,检查比值是否在允许区间内 merged = pd.merge(x_frames, init_stats, on='Particle') merged['IsWithinRange'] = (merged['Ratio'] >= merged['AvgRatio'] - 2*merged['StdRatio']) & \ (merged['Ratio'] <= merged['AvgRatio'] + 2*merged['StdRatio']) # 筛选出后续帧所有比值都在范围内的粒子 valid_particles = merged.groupby('Particle')['IsWithinRange'].all() valid_particles = valid_particles[valid_particles].index.tolist() # 输出结果 print("符合条件的粒子ID:", valid_particles) # 可选:输出符合条件的粒子所有数据 print("\n符合条件的粒子完整数据:") print(testframe[testframe['Particle'].isin(valid_particles)])
关键说明
- 若需求是只要后续有任意一帧超出范围就剔除,则用
all();若需求是只要有一帧在范围内就保留,则替换为any() - 后续帧范围可灵活调整,比如要对比后续3帧(Frame2-4),可改为
testframe[(testframe['Frame'] >= framenot) & (testframe['Frame'] <= framenot + 2)] - 原代码中的循环被
groupby替代,代码更简洁且性能更优
内容的提问来源于stack exchange,提问作者k07
相关产品推荐
相关产品推荐

