向量化方法,使用arange查找最后一个索引,max,并拼接:
df['last_referred'] = np.r_[[np.NaN], df.columns][
((df == 'referred') * (np.arange(df.shape[1]) + 1)).max(axis=1).values]
解释:
我们想在每一行中找到值'referred'的最右边的单元格:
>>> df == 'referred'
name action_1 action_2 action_3
0 False True True False
1 False False True True
2 False False False False
3 False False True False
4 False True False False
5 False False False False
一个选项是DataFrame.idxmax,但这给出了第一个(即最左边的)出现。然而,假设我们可以用它们的列索引替换True 值,我们可以只使用普通的max。由于True 是1 和False 是0,我们可以通过乘以整数范围[0, 1, 2, ...] 垂直广播:
>>> np.arange(df.shape[1])
array([0, 1, 2, 3])
>>> (df == 'referred') * np.arange(df.shape[1])
name action_1 action_2 action_3
0 0 1 2 0
1 0 0 2 3
2 0 0 0 0
3 0 0 2 0
4 0 1 0 0
5 0 0 0 0
>>> ((df == 'referred') * np.arange(df.shape[1])).max(axis=1)
0 2
1 3
2 0
3 2
4 1
5 0
dtype: int32
但有一个问题:我们无法区分“名称”列中的'referred' 和根本不出现之间的区别。易于修复;只需从 1 开始整数范围:
>>> ((df == 'referred') * (np.arange(df.shape[1]) + 1)).max(axis=1)
0 3
1 4
2 0
3 3
4 2
5 0
dtype: int32
现在只需使用这个数组来索引列名:
>>> df.columns[((df == 'referred') * (np.arange(df.shape[1]) + 1)).max(axis=1).values]
IndexError: index 4 is out of bounds for size 4
哎呀!我们需要让0 以NaN 的形式出现,其余的列要转移。我们可以使用np.r_ 来做到这一点,它连接数组:
>>> np.r_[[np.NaN], df.columns]
array([nan, 'name', 'action_1', 'action_2', 'action_3'], dtype=object)
>>> np.r_[[np.NaN], df.columns][
((df == 'referred') * (np.arange(df.shape[1]) + 1)).max(axis=1).values]
array(['action_2', 'action_3', nan, 'action_2', 'action_1', nan], dtype=object)
你有它。