将函数应用于 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 仅 Ai
和 Bi
列并反转它们的顺序 (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
我有以下函数获取一行的最后一个非零值的列名
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 仅 Ai
和 Bi
列并反转它们的顺序 (df.iloc[:, :1:-1]
) 然后 return 列每行 (.idxmax(axis=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