将函数应用于 pandas 数据框 (lambda) 中的所有行

Apply function to all rows in pandas dataframe (lambda)

我有以下函数获取一行的最后一个非零值的列名

import pandas as pd

def myfunc(X, Y):
    df = X.iloc[Y]
    counter = len(df)-1
    while counter >= 0:
        if df[counter] == 0:
            counter -= 1
        else:
            break
    return(X.columns[counter])

使用下面的代码示例

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)
df

myfunc(df, 5) # 'B1'

我想知道如何将此函数应用于数据框中的所有行,并将结果放入 df

的新列中

我正在考虑遍历所有行(这可能不是好的方法)或将 lambda 与 apply 函数一起使用。但是,我没有成功采用最后一种方法。有帮助吗?

我已经稍微修改了你的函数以跨行工作:

def myfunc(row):
     counter = len(row)-1
     while counter >= 0:
         if row[counter] == 0:
             counter -= 1
         else:
             break
     return row.index[counter]

现在只需调用 df.apply 您的函数,然后 axis=1 为数据帧的每一行调用函数:

>>> df.apply(myfunc, axis=1)
0    A2
1    A1
2    A2
3    C1
4    A2
5    B1
dtype: object

但是,您可以放弃您的自定义函数并使用此代码以更快、更简洁的方式完成您正在寻找的事情:

>>> df[df.columns[2:]].T.cumsum().idxmax()
0    A2
1    A1
2    A2
3    C1
4    A2
5    B1
dtype: object

这是使用 DataFrame.idxmax 的更简单、更快速的解决方案。

>>> res = df.iloc[:, :1:-1].idxmax(axis=1)
>>> res

0    A2
1    A1
2    A2
3    C1
4    A2
5    B1
dtype: object

想法是 select 仅 AiBi 列并反转它们的顺序 (df.iloc[:, :1:-1]) 然后 return 列每行 (.idxmax(axis=1)).

中第一次出现最大值(在本例中为 1)的标签

请注意,此解决方案(作为另一个答案)假定每一行包含至少一个大于零的条目。

如果我们首先屏蔽非零条目(使用 .ne(0)),则该假设可以放宽到 'each row contains at least one non-zero entry'。这是有效的,因为 .ne(0) 产生一个布尔掩码和 True > False <=> 1 > 0.

>>> res = df.iloc[:, :1:-1].ne(0).idxmax(axis=1)
res

0    A2
1    A1
2    A2
3    C1
4    A2
5    B1
dtype: object