我有一个DataFrame看起来像:

import pandas as pd

df = pd.DataFrame([[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0],
                   [9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0],
                   [17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0]],
                   columns=['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'])

      A     B     C     D     E     F     G     H
0   1.0   2.0   3.0   4.0   5.0   6.0   7.0   8.0
1   9.0  10.0  11.0  12.0  13.0  14.0  15.0  16.0
2  17.0  18.0  19.0  20.0  21.0  22.0  23.0  24.0


我有一个列列表:

l = ['A', 'C', 'D', 'E']


对于列表中的每个元素,我想获取其前面的数据框列的平均值,再加上其自己列中的值的两倍。因此,A仅取决于自身,C将取决于A及其本身,D将取决于AC及其自身的总和,而E将取决于ACD及其本身。我通过以下方式完成了我所需要的:

for i, col in enumerate(l):
    other_cols = l[:i]
    df['tmp_' + col] = df[other_cols].mean(axis=1) + 2.0 * df[col]

      A     B     C     D     E     F     G     H  tmp_A  tmp_C  tmp_D  \
0   1.0   2.0   3.0   4.0   5.0   6.0   7.0   8.0    NaN    7.0   10.0
1   9.0  10.0  11.0  12.0  13.0  14.0  15.0  16.0    NaN   31.0   34.0
2  17.0  18.0  19.0  20.0  21.0  22.0  23.0  24.0    NaN   55.0   58.0

       tmp_E
0  12.666667
1  36.666667
2  60.666667


我想知道是否还有一种更Python化的方法来完成相同的事情,而不必执行for循环?

最佳答案

IIUC,您可以在现代熊猫中使用expanding来处理此问题:

>>> cols = ["A","C","D","E"]
>>> df[cols] * 2 + df[cols].expanding(axis=1).mean().shift(axis=1).fillna(0)

      A     C     D          E
0   2.0   7.0  10.0  12.666667
1  18.0  31.0  34.0  36.666667
2  34.0  55.0  58.0  60.666667


这将重现您预期的新列(由于fillna将NaN变为0,A变为其原始值的两倍)。



我们可以逐步了解它的来源:

从...开始

>>> df[cols]

      A     C     D     E
0   1.0   3.0   4.0   5.0
1   9.0  11.0  12.0  13.0
2  17.0  19.0  20.0  21.0

>>> df[cols].expanding(axis=1)
Expanding [min_periods=1,center=False,axis=1]


我们可以先做sum,因为它在视觉上更容易检查:

>>> df[cols].expanding(axis=1).sum()

      A     C     D     E
0   1.0   4.0   8.0  12.0
1   9.0  20.0  32.0  36.0
2  17.0  36.0  56.0  60.0

>>> df[cols].expanding(axis=1).mean()

      A     C          D     E
0   1.0   2.0   2.666667   4.0
1   9.0  10.0  10.666667  12.0
2  17.0  18.0  18.666667  20.0

>>> df[cols].expanding(axis=1).mean().shift(axis=1)

    A     C     D          E
0 NaN   1.0   2.0   2.666667
1 NaN   9.0  10.0  10.666667
2 NaN  17.0  18.0  18.666667

>>> df[cols].expanding(axis=1).mean().shift(axis=1).fillna(0)

     A     C     D          E
0  0.0   1.0   2.0   2.666667
1  0.0   9.0  10.0  10.666667
2  0.0  17.0  18.0  18.666667

10-08 19:03