如何利用groupby,仅对某些行执行计算并保留所有列

时间:2019-06-12 21:15:41

标签: python pandas dataframe pandas-groupby

我正在尝试计算python大熊猫中时间序列数据的某些百分比变化。但是我在通过groupby进行处理并将正确的计算正确应用到正确的时间段数据时遇到了麻烦。 这是我当前拥有的数据框:

     A      B           C           D
0    ACTUAL 2018-03-01  249.498000  0.040000
1    ACTUAL 2018-06-01  251.134000  0.040000
2    ACTUAL 2018-09-01  252.010000  0.037000
3    ACTUAL 2018-12-01  252.723000  0.039000
4    ACTUAL 2019-03-01  254.148000  0.038000
5    TDA_D5 2019-03-01  253.393661  0.038667
6    TDA_D5 2019-06-01  254.329314  0.038229
7    TDA_D5 2019-09-01  254.784295  0.038974
8    TDA_D5 2019-12-01  254.988064  0.040149
9    TDA_D5 2020-03-01  255.158740  0.041696
10   TDA_D5 2020-06-01  255.243512  0.043405
11   TDA_D5 2020-09-01  255.360638  0.045753
12   TDA_D5 2020-12-01  255.445890  0.047833
13   TDA_D5 2021-03-01  255.700028  0.051772
14   TDA_D5 2021-06-01  256.001398  0.054357
15   TDA_D5 2021-09-01  256.347487  0.056077
16   TDA_D5 2021-12-01  256.792392  0.056796
17   TDA_D5 2022-03-01  257.314624  0.057218
18   TDA_D5 2022-06-01  257.922474  0.057385
19   TDA_U5 2019-03-01  253.393661  0.038667
20   TDA_U5 2019-06-01  255.882782  0.036118
21   TDA_U5 2019-09-01  258.415239  0.034246
22   TDA_U5 2019-12-01  261.090022  0.032766
23   TDA_U5 2020-03-01  264.033754  0.031713
24   TDA_U5 2020-06-01  267.157258  0.030939
25   TDA_U5 2020-09-01  270.563024  0.030997
26   TDA_U5 2020-12-01  274.090429  0.031201
27   TDA_U5 2021-03-01  277.877144  0.032869
28   TDA_U5 2021-06-01  281.790593  0.033901
29   TDA_U5 2021-09-01  285.838634  0.034656
30   TDA_U5 2021-12-01  289.992294  0.035058
31   TDA_U5 2022-03-01  294.235605  0.035529
32   TDA_U5 2022-06-01  298.547907  0.036048
33  TD_BASE 2019-03-01  253.393661  0.038667
34  TD_BASE 2019-06-01  255.119961  0.037143
35  TD_BASE 2019-09-01  256.589769  0.036490
36  TD_BASE 2019-12-01  257.949582  0.036184
37  TD_BASE 2020-03-01  259.351461  0.036187
38  TD_BASE 2020-06-01  260.702463  0.036312
39  TD_BASE 2020-09-01  262.093917  0.037062
40  TD_BASE 2020-12-01  263.422911  0.037667
41  TD_BASE 2021-03-01  264.883181  0.039809
42  TD_BASE 2021-06-01  266.351643  0.041000
43  TD_BASE 2021-09-01  267.828346  0.041699
44  TD_BASE 2021-12-01  269.313336  0.041867
45  TD_BASE 2022-03-01  270.806660  0.042033
46  TD_BASE 2022-06-01  272.308363  0.042199

我要实现的目标是在A列上使用groupby,如果它不等于“ ACTUAL”,则获取每个组的前4行(分别是“ TDA_D5”,“ TDA_U5”和“ TD_BASE”在这种情况下,由于我不想从A列获取“ ACTUAL”,因此在方程式中将这4行的每一行用于每个组的C列,而A列的C列值为“ ACTUAL”。

这意味着我将拥有方程

y = index-5.column-C / index-0.column-C - 1 * 100
对于分子,该方程将对索引6,索引7和索引8重复,但是对于组TDA_D5,分母分别为索引1、2和3。然后这也适用于索引19到22作为组TDA_U5的分子,分母仍为索引0到3,而分母33到36作为TD_BASE组的分子,分母仍为索引0到3。 >

到目前为止,我已经尝试了代码

a.groupby('A')['C'].apply(lambda x: (x.iloc[0:4] / 100)).reset_index()

我正在使用/ 100,因为我只是首先尝试测试是否可以将每个组的前4条记录应用于简单的100除法公式,因为我尚未弄清楚如何将其应用于我上面提到的方程式中实际组的前4条记录。我能够使用这段代码来获取系列对象,并使每个组(包括“ ACTUAL”组)的前四个记录除以100,但这就是我现在遇到的问题。我不知道如何在A中除“ ACTUAL”组之外的每个组的4条记录的子集上实现我试图实现的最终公式。 预先感谢!

1 个答案:

答案 0 :(得分:0)

你还没那么远。

df[df.A != 'ACTUAL'].groupby('A').apply(lambda x: pd.DataFrame(
                                 (x.iloc[:4].reset_index()['C']/df.iloc[:4]['C'] - 1) * 100))

给予:

                  C
A                  
TDA_D5  0  1.561400
        1  1.272354
        2  1.100867
        3  0.896263
TDA_U5  0  1.561400
        1  1.890936
        2  2.541661
        3  3.310748
TD_BASE 0  1.561400
        1  1.587185
        2  1.817297
        3  2.068107

或者您更希望将A列中的标签作为列:

df[df.A != 'ACTUAL'].groupby('A').apply(lambda x: (x.iloc[:4].reset_index()['C']
                                                   /df.iloc[:4]['C'] - 1) * 100).T

给出:

A    TDA_D5    TDA_U5   TD_BASE
C                              
0  1.561400  1.561400  1.561400
1  1.272354  1.890936  1.587185
2  1.100867  2.541661  1.817297
3  0.896263  3.310748  2.068107

如果您希望将其放回原始数据框中,则它会稍微复杂些,因为您必须保留原始索引。您可以这样做:

actual = df[df.A == 'ACTUAL']

out = df[df.A != 'ACTUAL'].groupby('A').apply(
    lambda x: x.iloc[:len(actual)].assign(
        resul=((x.iloc[:len(actual)].reset_index()['C']/
                actual.reset_index()['C'] -1)*100).values)).reset_index(
                    level=0, drop=True)

它给出:

          A           B           C         D     resul
5    TDA_D5  2019-03-01  253.393661  0.038667  1.561400
6    TDA_D5  2019-06-01  254.329314  0.038229  1.272354
7    TDA_D5  2019-09-01  254.784295  0.038974  1.100867
8    TDA_D5  2019-12-01  254.988064  0.040149  0.896263
9    TDA_D5  2020-03-01  255.158740  0.041696  0.397697
19   TDA_U5  2019-03-01  253.393661  0.038667  1.561400
20   TDA_U5  2019-06-01  255.882782  0.036118  1.890936
21   TDA_U5  2019-09-01  258.415239  0.034246  2.541661
22   TDA_U5  2019-12-01  261.090022  0.032766  3.310748
23   TDA_U5  2020-03-01  264.033754  0.031713  3.889763
33  TD_BASE  2019-03-01  253.393661  0.038667  1.561400
34  TD_BASE  2019-06-01  255.119961  0.037143  1.587185
35  TD_BASE  2019-09-01  256.589769  0.036490  1.817297
36  TD_BASE  2019-12-01  257.949582  0.036184  2.068107
37  TD_BASE  2020-03-01  259.351461  0.036187  2.047414

现在,由于有了索引,您现在可以将其放回原始数据框中:

df.loc[out.index, 'resul'] = out['resul']