Маска Pandas, GroupBy и CumSum

#python #pandas #pandas-groupby

#python #pandas #pandas-groupby

Вопрос:

Как я могу выполнить скользящую сумму столбца Trade_Cost , когда столбец Buy(C)/Sell(V) находится C , и сбрасывать эту сумму каждый раз Current_Qntd при попадании 0 , а затем запускать новую скользящую сумму до следующего zero ?

      Buy(C)/Sell(V)   Qntd     Price  Current_Qntd    Trade_Cost
0               C  33000  103.980000         33000  3.431340e 06
1               C   3682  102.940000         36682  3.790251e 05
2               C    108  103.490000         36790  1.117692e 04
3               C  10717  103.500000         47507  1.109210e 06
4               C   6831  103.760000         54338  7.087846e 05
5               C    968  107.000000         55306  1.035760e 05
6               C     32  107.000000         55338  3.424000e 03
7               V   3644  115.618296         51694  4.213131e 05
8               V   4704  115.995689         46990  5.456437e 05
9               V  46990  116.030000             0  5.452250e 06
10              C  35000  116.000000         35000  4.060000e 06
11              C  16000  117.999073         51000  1.887985e 05
12              V   1200  115.274742         49800  1.383297e 05
13              V   1400  116.700036         48400  1.633800e 05
14              V  23855  116.406567         24545  2.776879e 06
15              V   2589  116.247625         21956  3.009651e 05
16              V  12741  115.952801          9215  1.477355e 06
17              V   9132  115.951078            83  1.058865e 06
18              V     83  115.950000             0  9.623850e 03
  

Редактировать:

Я получил ответ ниже из другого вопроса, который я разместил здесь, в StackOverflow, но он не соответствует моим потребностям, потому что у меня много ресурсов в этом df, а приведенный выше пример предназначен только для одного ресурса.

 grp = (df['Current_Qntd'] == 0).cumsum()

df['Trade_Cost Sum'] = df['Trade_Cost'].mask(df['Buy(C)/Sell(V)'] != 'C', 0)

df['Trade_Cost Sum'] = df.groupby(grp)['Trade_Cost Sum'].cumsum()
  

Приведенный выше ответ отлично работает для DF только с одним активом, но мне нужно было бы сгруппировать по активу в DF со многими активами. Ниже приводится продолжение вышеупомянутого DF, но с двумя активами

 Buy(C)/Sell(V)  Qntd       Price  Current_Qntd     Trade_Cost    Asset
0                C   100  114.290000           100   11429.000000    2
1                C  3137  115.020000          3237  360817.740000    2
2                V   100  114.500000          3137   11450.000000    2
3                V  1200  114.670000          1937  137604.000000    2
4                V  1937  115.000000             0  222755.000000    2
5                C  5586   96.790000          5586  540668.940000    2
6                V  5586  116.590000             0  651271.740000    2
7                C   971  118.630000           971  115189.730000    2
8                V   971  129.800000             0  126035.800000    2
9                C   600  126.416417           600   75849.850002    2
10               C  33000  103.980000         33000  3.431340e 06    1
11               C   3682  102.940000         36682  3.790251e 05    1
12               C   108  103.490000         36790  1.117692e 04     1
13               C  10717  103.500000         47507  1.109210e 06    1
14               C   6831  103.760000         54338  7.087846e 05    1
15               C    968  107.000000         55306  1.035760e 05    1
16               C     32  107.000000         55338  3.424000e 03    1
17               V   3644  115.618296         51694  4.213131e 05    1
18               V   4704  115.995689         46990  5.456437e 05    1
19               V  46990  116.030000             0  5.452250e 06    1
20               C 35000  116.000000         35000  4.060000e 06     1
21               C 16000  117.999073         51000  1.887985e 06     1
22               V  1200  115.274742         49800  1.383297e 05     1
23               V  1400  116.700036         48400  1.633800e 05     1
24               V 23855  116.406567         24545  2.776879e 06     1
25               V  2589  116.247625         21956  3.009651e 05     1
26               V 12741  115.952801          9215  1.477355e 06     1
27               V  9132  115.951078            83  1.058865e 06     1
28               V    83  115.950000             0  9.623850e 03     1
  

ПРАВКА 2:

grp = (df['Current_Qntd'] == 0).cumsum() группирует ли 2 разных ресурса с помощью current_qntd = 0, как я могу сгруппировать его по активу?

Комментарии:

1. Добавьте ‘Asset’ вместе с grp : df.groupby(['Asset', grp])...

2. Ваш вопрос звучит сложнее, чем есть на самом деле. Current_Qntd переходит в 0 всякий раз, когда у группы есть Buy(C)/Sell(V) == V , поэтому просто определите свой groupby() по некоторому списку столбцов.

3. Я добавил ресурс в groupby, как сказал @QuangHoang, но он неправильно выполняет cumsum после того, как Current_Qntd достигнет нуля

4. @smci Я считаю, что есть проблема grp = (df['Current_Qntd'] == 0).cumsum() , потому что, когда я добавляю его в качестве столбца и фильтрую столбец по grp, я вижу разные активы с одинаковым номером grp

5. Тогда вы должны groupby(['Asset', grp], ...) , как сказал QuangHoang. Когда вы говорите «но он неправильно выполняет cumsum после того, как Current_Qntd достигнет нуля» , пожалуйста, покажите вывод и точно объясните, почему это неправильно.

Ответ №1:

Затем вы просто группируете по только что созданному столбцу и активу, нет?

 grp = (df['Current_Qntd'] == 0).cumsum()

df['Trade_Cost Sum'] = df['Trade_Cost'].mask(df['Buy(C)/Sell(V)'] != 'C', 0)

df['Trade_Cost Sum'] = df.groupby(["Asset", grp])['Trade_Cost Sum'].cumsum()
  

Создает это:

    Buy(C)/Sell(V)   Qntd       Price  ...    Trade_Cost  Asset  Trade_Cost Sum
0               C    100  114.290000  ...  1.142900e 04      2    1.142900e 04
1               C   3137  115.020000  ...  3.608177e 05      2    3.722467e 05
2               V    100  114.500000  ...  1.145000e 04      2    3.722467e 05
3               V   1200  114.670000  ...  1.376040e 05      2    3.722467e 05
4               V   1937  115.000000  ...  2.227550e 05      2    0.000000e 00
5               C   5586   96.790000  ...  5.406689e 05      2    5.406689e 05
6               V   5586  116.590000  ...  6.512717e 05      2    0.000000e 00
7               C    971  118.630000  ...  1.151897e 05      2    1.151897e 05
8               V    971  129.800000  ...  1.260358e 05      2    0.000000e 00
9               C    600  126.416417  ...  7.584985e 04      2    7.584985e 04
10              C  33000  103.980000  ...  3.431340e 06      1    3.431340e 06
11              C   3682  102.940000  ...  3.790251e 05      1    3.810365e 06
12              C    108  103.490000  ...  1.117692e 04      1    3.821542e 06
13              C  10717  103.500000  ...  1.109210e 06      1    4.930752e 06
14              C   6831  103.760000  ...  7.087846e 05      1    5.639537e 06
15              C    968  107.000000  ...  1.035760e 05      1    5.743113e 06
16              C     32  107.000000  ...  3.424000e 03      1    5.746537e 06
17              V   3644  115.618296  ...  4.213131e 05      1    5.746537e 06
18              V   4704  115.995689  ...  5.456437e 05      1    5.746537e 06
19              V  46990  116.030000  ...  5.452250e 06      1    0.000000e 00
20              C  35000  116.000000  ...  4.060000e 06      1    4.060000e 06
21              C  16000  117.999073  ...  1.887985e 06      1    5.947985e 06
22              V   1200  115.274742  ...  1.383297e 05      1    5.947985e 06
23              V   1400  116.700036  ...  1.633800e 05      1    5.947985e 06
24              V  23855  116.406567  ...  2.776879e 06      1    5.947985e 06
25              V   2589  116.247625  ...  3.009651e 05      1    5.947985e 06
26              V  12741  115.952801  ...  1.477355e 06      1    5.947985e 06
27              V   9132  115.951078  ...  1.058865e 06      1    5.947985e 06
28              V     83  115.950000  ...  9.623850e 03      1    0.000000e 00
  

Обратите внимание, что сумма торговых затрат в строке 10 совпадает с суммой торговых затрат для этой строки, поэтому совокупная сумма сбрасывается правильно.

Комментарии:

1. Я считаю, что есть проблема grp = (df['Current_Qntd'] == 0).cumsum() , потому что, когда я добавляю его в качестве столбца и фильтрую столбец по grp, я вижу разные активы с одинаковым номером grp