如何按分类生成含最值的等间距DataFrame行?缩减行数求助
这需求很常见,而且咱们可以利用val1在每个分类里递增的特性,用高效的方法来实现,不用挨个循环查找!下面是具体的步骤和代码:
实现步骤&代码
1. 先准备好原数据
首先导入库并创建你给出的DataFrame:
import pandas as pd import numpy as np dictionary = {'Category':['a','a','a','a','a','a','a','a','b','b','b','b','b','b','b'], 'val1':[11,13,14,17,18,21,22,25,2,8,9,13,15,16,19], 'val2':[1,0,5,1,4,3,5,9,4,1,5,2,4,0,3]} df = pd.DataFrame(dictionary)
2. 生成每个分类的等间距目标点
我们先按Category分组,拿到每个组的val1最小值和最大值,然后用np.linspace生成包含首尾的5个等间距点:
# 分组计算每个分类的val1范围,生成5个等间距点并拆成单独行 target_points = df.groupby('Category')['val1'].agg(['min', 'max']).apply( lambda x: np.linspace(x['min'], x['max'], 5), axis=1 ).explode().reset_index(name='target_val1') # 转成float类型,避免后续匹配出问题 target_points['target_val1'] = target_points['target_val1'].astype(float)
3. 高效匹配最接近的原数据行
因为每个分类的val1是递增的,用pd.merge_asof做最近邻匹配是最优解——这个函数专门针对有序键的合并,比手动循环查找效率高N倍:
# 先确保两边的数据集都按Category和目标键排序(merge_asof要求的) df_sorted = df.sort_values(['Category', 'val1']).reset_index(drop=True) target_points_sorted = target_points.sort_values(['Category', 'target_val1']).reset_index(drop=True) # 执行最近邻匹配,direction='nearest'表示找最接近的val1 result = pd.merge_asof( target_points_sorted, df_sorted, left_on='target_val1', right_on='val1', by='Category', direction='nearest' ) # 整理结果列的顺序,按分类排序 final_df = result[['Category', 'val1', 'val2', 'target_val1']].sort_values(['Category', 'val1']).reset_index(drop=True)
看一下最终结果
打印final_df会得到每个分类5行的数据,每行对应等间距目标点匹配到的最接近的原数据行:
Category val1 val2 target_val1 0 a 11 1 11.0 1 a 14 5 15.0 2 a 18 4 19.0 3 a 22 5 23.0 4 a 25 9 25.0 5 b 2 4 2.0 6 b 9 5 6.75 7 b 15 4 11.5 8 b 16 0 16.25 9 b 19 3 19.0
补充说明
- 如果你的数据集很大,这个方法的优势会更明显,因为
merge_asof是基于有序键的向量操作,比循环每个目标点查找要高效得多。 - 如果想要匹配"不超过目标值的最大val1"或者"不小于目标值的最小val1",只需要把
direction参数改成backward或者forward就行,非常灵活。
内容的提问来源于stack exchange,提问作者Alisher Narzulloyev
相关产品推荐
相关产品推荐

