数据框和系列的元素乘积以及组内的滚动总和

Element-wise product of dataframe and a series alongwith rolling sum within the group

我有一个 len n 的大数据框 dfn ~ 200 万行),列 nameqty 以及系列 wt 尺寸 m(m ~ 70)。在由 name 列中的值定义的每个组中,我想将 qtywt 相乘并进行滚动求和。例如,假设 dfwt 定义如下:

>>> import pandas as pd
>>> import numpy as np
>>> df = pd.DataFrame({'name':['abd']*3 + ['pqr']*5 + ['xyz']*8, 'qty':range(16)})
>>> df.iloc[2, 1] = np.nan
>>> df
       name qty
    0   abd   0
    1   abd   1
    2   abd NaN
    3   pqr   3
    4   pqr   4
    5   pqr   5
    6   pqr   6
    7   pqr   7
    8   xyz   8
    9   xyz   9
    10  xyz  10
    11  xyz  11
    12  xyz  12
    13  xyz  13
    14  xyz  14
    15  xyz  15
>>> wt = pd.Series([0.1, 0.2, 0.3, 0.4])
>>> wt
    0    0.1
    1    0.2
    2    0.3
    3    0.4

想要的输出wtdsum如下:

       name qty wtdsum
    0   abd   0    0.2
    1   abd   1    0.1
    2   abd NaN    0.0
    3   pqr   3    5.0
    4   pqr   4    6.0
    5   pqr   5    3.8
    6   pqr   6    2.0
    7   pqr   7    0.7
    8   xyz   8   10.0
    9   xyz   9   11.0
    10  xyz  10   12.0
    11  xyz  11   13.0
    12  xyz  12   14.0
    13  xyz  13    8.6
    14  xyz  14    4.4
    15  xyz  15    1.5

为下面的 wtdsum 添加一些示例计算:
行号 0:0*0.1 + 1*0.2 + NaN*0.3 = 0.2
行号 1:1*0.1 + NaN*0.2 = 0.1
行号 2:NaN*0.1 = 0.0
行号 3:3*0.1 + 4*0.2 + 5*0.3 + 6*0.4 = 5.0
行号 4:4*0.1 + 5*0.2 + 6*0.3 + 7*0.4 = 6.0
行号 5:5*0.1 + 6*0.2 + 7*0.3 = 3.8
行号 6:6*0.1 + 7*0.2 = 2.0
行号 7:7*0.1 = 0.7
行号 8:8*0.1 + 9*0.2 + 10*0.3 + 11*0.4 = 10.0
...
行号 15:15*0.1 = 1.5

到此为止,已在完成,希望不会有问题。这有点乏味,但我会尽力解释:

  • 首先我们创建一个变量"indicator",它将告诉我们当前组中还有多少元素。 .apply() 中的第一项为每个 "name" 创建一个出现次数最多的向量。然后我们减去每一行中已经发生的次数。因此,我们获得了每个特定 "name" 的剩余案例数。然后我们取这个数字和 wt.

    的长度之间的最小值
  • 然后我们用.apply()根据这个"indicator"进行计算。在第二个 .apply() 中,我们基本上根据每个 name.

    剩余的案例数来执行您在问题中解释的计算。
      import pandas as pd
      import numpy as np
      df = pd.DataFrame({'name':['abd']*3 + ['pqr']*5 + ['xyz']*8, 'qty':range(16)})
      df.iloc[2, 1] = np.nan
    
      wt = pd.Series([0.1, 0.2, 0.3, 0.4])
    
      df["indicator"] = np.minimum(df["name"].map(dict(df.fillna(0).groupby("name").count()["qty"])) - \
                                   df.groupby("name").cumcount(),
                                   len(wt))
    
      df["wtsum"] = df.apply(lambda x: np.sum(np.asarray((wt[range(0,x[2])]))*\
                                       np.asarray(df.fillna(0).iloc[list(range(x.name,x.name + x[2])),1])),\
                             axis = 1)
    
      df[["name","qty","wtsum"]]
    

    输出:

          name  qty   wtsum
      0   abd   0.0   0.2
      1   abd   1.0   0.1
      2   abd   NaN   0.0
      3   pqr   3.0   5.0
      4   pqr   4.0   6.0
      5   pqr   5.0   3.8
      6   pqr   6.0   2.0
      7   pqr   7.0   0.7
      8   xyz   8.0   10.0
      9   xyz   9.0   11.0
      10  xyz   10.0  12.0
      11  xyz   11.0  13.0
      12  xyz   12.0  14.0
      13  xyz   13.0  8.6
      14  xyz   14.0  4.4
      15  xyz   15.0  1.5