矢量化方法,使用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
。
>>> 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
一個問題,雖然:由於True
是1
和False
是0
,我們可以通過與整數範圍[0, 1, 2, ...]
廣播垂直乘以做到這一點,我們不能告訴'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)
有你有它。
我想你可以用幾種不同的方式做矢量化 – Jeff
我很欣賞@ecatmur答案的速度,但我不明白。我沒有使用一個巨大的數據集(應該在我的原始問題中注意到這一點),所以我很欣賞這裏更直接的方法。 – bjornarneson
如果你評估@ ecatmur的答案,你會很快把它記住,它只是寫得太簡單了。 –