簡體   English   中英

Pandas 兩列條件滾動和

[英]Pandas Conditional Rolling Sum of Two Columns

我在數據框中有四列,如下所示:

       A   B     C        D
75472  d1  x    -36.0   0.0
75555  d2  x    -38.0   0.0
75638  d3  x    -18.0   0.0
75721  d4  x    -18.0   1836.0
75804  d5  x    1151.0  0.0
75887  d6  x    734.0   0.0
75970  d7  x    -723.0  0.0

我想有條件地對D求和:

  • D 有值,則 D
  • 否則,從 D 的上一行取值加上 C

因此,對於上述情況, D 將是[-36, -74, -92, 1836, 2987, 3721, 2998]

我已經能夠使用 for 循環成功地做到這一點

for i, row in me.iterrows():
    try:
        if row['D'] > 0:
            step1 = me.loc[(me['B'] == row['B']) & (me['A'] == row['A']), 'output'].iloc[0]
            me_copy.iloc[i, me_copy.columns.get_loc('output')] = step1
        else:
            step1 = me.loc[(me['B'] == row['B']) & (me['A'] == (row['A'] - pd.DateOffset(days=1))), 'step1'].iloc[0]
            receipts_adjustments_sales = me.loc[(me['B'] == row['B']) & (me['A'] == row['A']), 'C'].iloc[0]
            me_copy.iloc[i, me_copy.columns.get_loc('output')] = step1 + receipts_adjustments_sales
    except:
        me_copy.iloc[i, me_copy.columns.get_loc('output')] = 0

但是 for 循環顯然非常昂貴,反模式並且基本上不會運行在我的整個數據幀上。 我正在嘗試復制 excel function 這里基本上已經寫在一組數據上,對於我的一生,我無法弄清楚如何做到這一點:

  • pd.Series.shift()
  • pd.Series.rolling()
  • 簡單地計算不同的列值

我試圖用shift()來做一段時間,但我意識到我必須為每一行創建一個單獨的列,這就是我使用 for 循環的原因。

泛化到組

df.loc[:, 'A_group'] = df.groupby(['A'])[df['D'] != 0].cumsum()
df.loc[:, 'E'] = df['D'].mask(df['D'] == 0).combine_first(df['C'])
df.loc[:, 'F'] = me.groupby(['A', 'A_group'])['E'].cumsum()

感謝斯科特波士頓的幫助!

這是一種方法:

grp = (df['D'] != 0).cumsum()
df['D_new'] = df['D'].mask(df['D'] == 0).combine_first(df['C']).groupby(grp).cumsum()
df

Output:

        A  B       C       D   D_new
75472  d1  x   -36.0     0.0   -36.0
75555  d2  x   -38.0     0.0   -74.0
75638  d3  x   -18.0     0.0   -92.0
75721  d4  x   -18.0  1836.0  1836.0
75804  d5  x  1151.0     0.0  2987.0
75887  d6  x   734.0     0.0  3721.0
75970  d7  x  -723.0     0.0  2998.0

細節:

創建 grps 來幫助 cumsum。 每個組都定義為 'D' 中出現的值,因此您在之前停止 cumsum 並選擇 D 的值並繼續 cumsum 直到 'D' 的下一個值

grp = (df['D'] != 0).cumsum()

Output:

        A  B       C       D   D_new  grp
75472  d1  x   -36.0     0.0   -36.0    0
75555  d2  x   -38.0     0.0   -74.0    0
75638  d3  x   -18.0     0.0   -92.0    0
75721  d4  x   -18.0  1836.0  1836.0    1
75804  d5  x  1151.0     0.0  2987.0    1
75887  d6  x   734.0     0.0  3721.0    1
75970  d7  x  -723.0     0.0  2998.0    1

現在,當 D 具有非零數時,讓我們創建結合 'C' 和 'D' 的新列

df['newCD'] = df['D'].mask(df['D'] == 0).combine_first(df['C'])

Output:

        A  B       C       D   D_new  grp   newCD
75472  d1  x   -36.0     0.0   -36.0    0   -36.0
75555  d2  x   -38.0     0.0   -74.0    0   -38.0
75638  d3  x   -18.0     0.0   -92.0    0   -18.0
75721  d4  x   -18.0  1836.0  1836.0    1  1836.0
75804  d5  x  1151.0     0.0  2987.0    1  1151.0
75887  d6  x   734.0     0.0  3721.0    1   734.0
75970  d7  x  -723.0     0.0  2998.0    1  -723.0

最后,groupby 'grp' 和cumsum newCD:

df['D_new_Details'] = df.groupby('grp')['newCD'].cumsum()

Output:

        A  B       C       D   D_new  grp   newCD  D_new_Details
75472  d1  x   -36.0     0.0   -36.0    0   -36.0          -36.0
75555  d2  x   -38.0     0.0   -74.0    0   -38.0          -74.0
75638  d3  x   -18.0     0.0   -92.0    0   -18.0          -92.0
75721  d4  x   -18.0  1836.0  1836.0    1  1836.0         1836.0
75804  d5  x  1151.0     0.0  2987.0    1  1151.0         2987.0
75887  d6  x   734.0     0.0  3721.0    1   734.0         3721.0
75970  d7  x  -723.0     0.0  2998.0    1  -723.0         2998.0

另一個,類似於斯科特的回答:

groups = df['D'].ne(0).cumsum()
df['new'] = (df['C'].where(df['D'].eq(0), df['D'])
     .groupby(groups)
     .cumsum()
)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM