如何在Pandas DataFrame多列中获取与指定值最接近的高低值
解决方案
下面提供两种实现方式,分别适合小数据集的直观处理和大数据集的高效矢量化运算:
方法一:逐行处理(直观易懂)
通过apply函数对每行数据单独处理,逻辑清晰,适合理解和调试:
import pandas as pd # 构造原始DataFrame id = [1001, 1002, 1003] a = [156, 224, 67] b = [131, 203, 61] c = [97, 165, 54] d = [68, 122, 50] value = [71, 180, 66] df = pd.DataFrame({'id':id, 'a':a, 'b':b, 'c':c, 'd':d, 'value':value}) def get_nxt_values(row): # 提取当前行的a-d列数值 col_values = row[['a', 'b', 'c', 'd']].values current_value = row['value'] # 筛选小于value的数值,取最大值作为nxt_low lower_vals = col_values[col_values < current_value] nxt_low = lower_vals.max() if len(lower_vals) > 0 else None # 筛选大于value的数值,取最小值作为nxt_high higher_vals = col_values[col_values > current_value] nxt_high = higher_vals.min() if len(higher_vals) > 0 else None return pd.Series([nxt_low, nxt_high], index=['nxt_low', 'nxt_high']) # 应用函数到每行,生成新列 df[['nxt_low', 'nxt_high']] = df.apply(get_nxt_values, axis=1) print(df)
运行后输出结果:
id a b c d value nxt_low nxt_high 0 1001 156 131 97 68 71 68 97 1 1002 224 203 165 122 180 165 203 2 1003 67 61 54 50 66 61 67
方法二:矢量化运算(高效处理大数据集)
利用numpy广播特性,避免逐行循环,处理大规模数据时性能更优:
import pandas as pd import numpy as np # 构造原始DataFrame id = [1001, 1002, 1003] a = [156, 224, 67] b = [131, 203, 61] c = [97, 165, 54] d = [68, 122, 50] value = [71, 180, 66] df = pd.DataFrame({'id':id, 'a':a, 'b':b, 'c':c, 'd':d, 'value':value}) # 提取a-d列转为二维数组,value转为列向量(用于广播) ad_array = df[['a', 'b', 'c', 'd']].to_numpy() value_array = df['value'].to_numpy()[:, np.newaxis] # 计算nxt_low:每行中小于value的最大值 lower_mask = ad_array < value_array # 将不满足条件的数值替换为负无穷,再取每行最大值 nxt_low = np.where( lower_mask.any(axis=1), np.max(np.where(lower_mask, ad_array, -np.inf), axis=1), None ) # 计算nxt_high:每行中大于value的最小值 higher_mask = ad_array > value_array # 将不满足条件的数值替换为正无穷,再取每行最小值 nxt_high = np.where( higher_mask.any(axis=1), np.min(np.where(higher_mask, ad_array, np.inf), axis=1), None ) # 将结果赋值回DataFrame df['nxt_low'] = nxt_low df['nxt_high'] = nxt_high print(df)
此方法输出结果与方法一完全一致,但处理十万级以上数据时,速度会远快于逐行处理。
内容的提问来源于stack exchange,提问作者wsilva916
相关产品推荐
相关产品推荐

