pandas dataframe如何通过lambda/apply对所有行执行自定义函数获取最后非零值列名
解决方案
核心思路是先筛选出需要参与非零判断的数值列(示例中为A1/B1/C1/A2,排除id、name等非数值列),根据数据量大小可以选择以下两种方案:
方案1:向量化实现(推荐,大数据量效率更高)
完全基于pandas内置向量化操作,性能比遍历、apply写法高1~2个数量级,适合万行以上的大表使用:
import pandas as pd data = {'id': ['1', '2', '3', '4', '5', '6'], 'name': ['AAA', 'BBB', 'CCC', 'DDD', 'EEE', 'GGG'], 'A1': [1, 1, 1, 0, 1, 1], 'B1': [0, 0, 1, 0, 0, 1], 'C1': [1, 0, 1, 1, 0, 0], 'A2': [1, 0, 1, 0, 1, 0]} df = pd.DataFrame(data) # 筛选需要检查的列,倒序排列方便直接取第一个非零列 check_cols_reversed = df.columns[2:][::-1] df['last_non_zero_col'] = df[check_cols_reversed].ne(0).idxmax(axis=1)
方案2:apply实现(写法简单,适合小数据量)
如果数据量在千行级别以内,可以用更易读的apply写法。你之前调用apply失败是因为原函数参数是接收全量df和行索引,而apply按行遍历时传入的是单行的Series对象,调整函数参数适配即可:
def get_last_non_zero(row, check_cols): # 倒序遍历检查列,返回第一个非零的列名 for col in check_cols[::-1]: if row[col] != 0: return col check_cols = df.columns[2:] df['last_non_zero_col'] = df.apply(lambda x: get_last_non_zero(x, check_cols), axis=1)
结果验证
两种方案运行后,新列last_non_zero_col的输出均符合预期:
0 A2 1 A1 2 A2 3 C1 4 A2 5 B1 Name: last_non_zero_col, dtype: object
如果是极小数据量,你也可以直接用原函数遍历实现,仅需少量修改即可:
# 不推荐,性能最低,仅适合极小规模数据 for i in range(len(df)): df.loc[i, 'last_non_zero_col'] = myfunc(df, i)
内容的提问来源于stack exchange,提问作者moon289
相关产品推荐
相关产品推荐

