如何在DataFrame中创建变量提取每行最后有效响应及对应列
解决DataFrame每行提取最后一个有效值及对应列名的问题
我来帮你搞定这个需求!用Pandas可以轻松实现从初始DataFrame到目标DataFrame的转换,下面是具体的代码和解释:
步骤1:构造初始DataFrame
首先我们先把你给出的初始数据转换成可运行的Pandas DataFrame:
import pandas as pd import numpy as np # 构造初始DataFrame df = pd.DataFrame({ 'id': [1, 2, 3, 4, 5, 6], 'X_1': [1, 2, 5, 6, 8, 12], 'X_2': [3, 4, 5, 6, 2, 3], 'X_3': [5, np.nan, 6, np.nan, 6, 2], 'X_4': [np.nan, np.nan, 5, np.nan, 6, 2], 'X_5': [np.nan, np.nan, 3, np.nan, 6, np.nan] })
步骤2:添加目标列
我们可以用两种高效的方式生成X_final和X_final_location列:
方法一:利用bfill和cumsum+idxmax(推荐,性能更优)
这种方法不需要逐行循环,适合处理大规模数据集:
# 提取所有以X_开头的列 x_cols = df.filter(like='X_') # 生成X_final:每行最后一个非NA值(bfill从右往左填充,取最后一列即可) df['X_final'] = x_cols.bfill(axis=1).iloc[:, -1] # 生成X_final_location:对应列名(cumsum标记非NA位置,idxmax取最后一个非NA的列) df['X_final_location'] = x_cols.notna().cumsum(axis=1).idxmax(axis=1)
方法二:利用apply逐行处理(逻辑更直观,适合小数据集)
如果觉得上面的方法有点抽象,也可以用逐行处理的方式,逻辑更清晰易懂:
# 提取X_开头的列 x_cols = df.filter(like='X_') # 定义函数:获取每行最后一个非NA值和对应列名 def get_last_valid(row): valid_entries = row.dropna() if not valid_entries.empty: return valid_entries.iloc[-1], valid_entries.index[-1] else: return np.nan, np.nan # 应用函数并拆分结果到两列 df[['X_final', 'X_final_location']] = x_cols.apply(get_last_valid, axis=1, result_type='expand')
最终结果
运行完上面的代码后,你就能得到和目标DataFrame完全一致的结果:
id X_1 X_2 X_3 X_4 X_5 X_final X_final_location 0 1 1 3 5.0 NaN NaN 5.0 X_3 1 2 2 4 NaN NaN NaN 4.0 X_2 2 3 5 5 6.0 5.0 3.0 3.0 X_5 3 4 6 6 NaN NaN NaN 6.0 X_2 4 5 8 2 6.0 6.0 6.0 6.0 X_5 5 6 12 3 2.0 2.0 NaN 2.0 X_4
注:如果你的数据中存在整行都是NA的情况,两种方法都会返回
NaN,你可以根据需求额外处理这种边缘情况。
内容的提问来源于stack exchange,提问作者user21027866
相关产品推荐
相关产品推荐

