我有以下的列True和False布林值。我想創建一個新列,對True值執行累積總和,如果該值被False重置,則計數,如下所示:
bool count
0 False 0
1 True 1
2 True 2
3 True 3
4 False 0
5 True 1
6 True 2
7 False 0
8 False 0
uj5u.com熱心網友回復:
是的,這可以通過一系列步驟來完成:
df['count'] = df.groupby(df['bool'].astype(int).diff().ne(0).cumsum())['bool'].cumsum()
輸出:
>>> df
bool count
0 False 0
1 True 1
2 True 2
3 True 3
4 False 0
5 True 1
6 True 2
7 False 0
8 False 0
解釋:
此代碼為假值 (0) 之前的所有連續真值 (1) 創建單獨的組,然后將真值視為 1,將假值視為 0,計算每個組的累積總和,然后將結果連接在一起。
df.groupby——df['bool'].astype(int)- 獲取 的每個值bool,將其轉換為 int (true -> 1, false -> 0),.diff()- 對于每個整數值,計算它與前一個值之間的差異(因此,如果 prev val 為 False 而 this 為 True,則為 1 (1 - 0);如果 prev 為 True 且此為 True,則為 0 (1 - 1);等等).ne(0)- 將所有不等于 0 的值轉換為真,將零轉換為假(因為(0 != 0) == False).cumsum()- 計算真 (1) 值的累積總和。這樣,任何 false (0) 之前的所有 true 都會獲得自己的唯一編號,該編號將回傳給groupby()呼叫,從而將 false 之前的每組 true 分別分組
['bool'].cumsum()- 從每組連續的真值 (1) 中,得到那些 1 的累積和。
uj5u.com熱心網友回復:
可能有一種更 Pythonic 的方法來做到這一點,但這里有一個簡單的迭代方法:
current_count = 0
for index, row in data.iterrows():
if (row['bool']):
current_count = 1
else:
current_count = 0
data.at[index, 'count'] = current_count
這data是最初有一個名為 的列的資料框bool,然后我們添加該count列!
uj5u.com熱心網友回復:
如果性能很重要,請使用此矢量化解決方案:
cumsum = df['bool'].cumsum()
df['count1'] = cumsum.sub(cumsum.where(~df['bool']).ffill().fillna(0).astype(int))
print (df)
bool count count1
0 False 0 0
1 True 1 1
2 True 2 2
3 True 3 3
4 False 0 0
5 True 1 1
6 True 2 2
7 False 0 0
8 False 0 0
說明:
首先在布爾列中使用累積總和,Trues 像1變數一樣處理cumsum(在列中cumsum)。
然后將 if Falses替換為~in Series.where(在 column 中add_NaNs)反轉掩碼,因此可能通過ffill(在 column 中forward_fill_NaNs)之前的值向前填充缺失值。
可以用于減去原始系列cumsum(在列中subtract)。
最后,如果NaN列開頭的某些s(未替換為ffill)使用Series.fillna并將輸出轉換為integers(在列中out)。
cumsum = df['bool'].cumsum()
print (df.assign(cumsum = cumsum,
add_NaNs = cumsum.where(~df['bool']),
forward_fill_NaNs= cumsum.where(~df['bool']).ffill(),
subtract = cumsum.sub(cumsum.where(~df['bool']).ffill()),
out = cumsum.sub(cumsum.where(~df['bool']).ffill().fillna(0).astype(int)))
)
bool count cumsum add_NaNs forward_fill_NaNs subtract out
0 False 0 0 0.0 0.0 0.0 0
1 True 1 1 NaN 0.0 1.0 1
2 True 2 2 NaN 0.0 2.0 2
3 True 3 3 NaN 0.0 3.0 3
4 False 0 3 3.0 3.0 0.0 0
5 True 1 4 NaN 3.0 1.0 1
6 True 2 5 NaN 3.0 2.0 2
7 False 0 5 5.0 5.0 0.0 0
8 False 0 5 5.0 5.0 0.0 0
性能(在樣本資料中,實際最佳測驗):
#9k rows
df = pd.concat([df] * 1000, ignore_index=True)
In [17]: %%timeit
...: current_count = 0
...: for index, row in df.iterrows():
...: if (row['bool']):
...: current_count = 1
...: else:
...: current_count = 0
...: df.at[index, 'count1'] = current_count
...:
1.06 s ± 5.54 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [18]: %%timeit
...: df['count1'] = df.groupby(df['bool'].astype(int).diff().ne(0).cumsum())['bool'].cumsum()
...:
...:
2.91 ms ± 39.8 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [19]: %%timeit
...: cumsum = df['bool'].cumsum()
...: df['count1'] = cumsum.sub(cumsum.where(~df['bool']).ffill().fillna(0).astype(int))
...:
1.38 ms ± 7.12 μs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
#900k rows
df = pd.concat([df] * 100000, ignore_index=True)
In [21]: %%timeit
...: df['count1'] = df.groupby(df['bool'].astype(int).diff().ne(0).cumsum())['bool'].cumsum()
...:
...:
105 ms ± 971 μs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [22]: %%timeit
...: cumsum = df['bool'].cumsum()
...: df['count1'] = cumsum.sub(cumsum.where(~df['bool']).ffill().fillna(0).astype(int))
...:
...:
42.5 ms ± 419 μs per loop (mean ± std. dev. of 7 runs, 10 loops each)
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/357488.html
標籤:Python 熊猫 数据框 布尔值 pandas-groupby
上一篇:如何在熊貓系列中找到最長的串列?
下一篇:熊貓:下降后價值仍然存在
