【问题标题】:Weighted Mean as a Column in Pandas加权平均值作为 Pandas 中的一列
【发布时间】:2021-08-28 17:25:45
【问题描述】:

我正在尝试添加具有 4 列权重的 4 列加权平均值的列

df = pd.DataFrame.from_dict(dict([('A', [2000, 1000, 2509, 2145]),
                                  ('A_Weight', [37, 47, 33, 16]),
                                  ('B', [2100, 1500, 2000, 1600]),
                                  ('B_weights', [17, 21, 6, 2]),
                                  ('C', [2500, 1400, 0, 2300]),
                                  ('C_weights', [5, 35, 0, 40]),
                                  ('D', [0, 1600, 2100, 2000]),
                                  ('D_weights', [0, 32, 10, 5])]))

我希望加权平均值出现在一个名为“WA”的新列中,但每次我尝试它都会显示 NaN

Desired Dataframe 将是一个新列,其中包含以下值:

我使用的公式(((A * A_weight)+(B * b_weight)+(C * C_weight)+(D * D_weight)) / sum(all weights)

df['WA'] = [2071.19,1323.70, 2363.20,2214.60 ]

谢谢

【问题讨论】:

    标签: python pandas multiple-columns calculated-columns weighted-average


    【解决方案1】:

    一个简单明了的方法如下:

    (由于您的权重列名称的命名不一致,例如,有些带有“s”,有些没有,有些带有大写“W”,有些带有小写“w”,因此对列进行分组并不方便,例如按.filter())

    df['WA'] = ( (df['A'] * df['A_Weight']) + (df['B'] * df['B_weights']) + (df['C'] * df['C_weights']) + (df['D'] * df['D_weights']) ) / (df['A_Weight'] + df['B_weights'] + df['C_weights'] + df['D_weights'])
    

    结果:

    print(df)
    
    
          A  A_Weight     B  B_weights     C  C_weights     D  D_weights           WA
    0  2000        37  2100         17  2500          5     0          0  2071.186441
    1  1000        47  1500         21  1400         35  1600         32  1323.703704
    2  2509        33  2000          6     0          0  2100         10  2363.204082
    3  2145        16  1600          2  2300         40  2000          5  2214.603175
    

    【讨论】:

      【解决方案2】:

      不那么直接的方式:

      1. 通过str.split按前缀对列进行分组
      2. 通过groupby prod 获取列式乘积
      3. 在轴 1 上获取带有 sum 的乘积的逐行总和。
      4. filter + sum 在轴 1 上获取“权重”列的总和
      5. 将组乘积总和除以权重总和。
      df['WA'] = (
              df.groupby(df.columns.str.split('_').str[0], axis=1).prod().sum(axis=1)
              / df.filter(regex='_[wW]eight(s)?$').sum(axis=1)
      )
      
            A  A_Weight     B  B_weights     C  C_weights     D  D_weights           WA
      0  2000        37  2100         17  2500          5     0          0  2071.186441
      1  1000        47  1500         21  1400         35  1600         32  1323.703704
      2  2509        33  2000          6     0          0  2100         10  2363.204082
      3  2145        16  1600          2  2300         40  2000          5  2214.603175
      

      【讨论】:

      • .filter() +1 正则表达式的良好使用
      • 谢谢@SeaBean。我想明确一点,你的答案应该是公认的答案,我只是想看看我是否可以这样做 XD(你已经得到了我的 +1)
      • 你的可以更好地扩展很多列。无论谁得到接受的答案都可以。 :-)
      • 也许用like=_作为分母过滤
      • @sammywemmy 是的,我尽可能具体。在这种情况下,假设没有其他带有下划线的列肯定有效。 regex='_' 也可以。
      【解决方案3】:

      老问题的另一种选择:

      将数据拆分为分子和分母:

      numerator = df.filter(regex=r"[A-Z]$")
      denominator = df.filter(like='_')
      

      denominator 转换为MultiIndex,在使用numerator 计算时会派上用场:

      denominator.columns = denominator.columns.str.split('_', expand = True)
      

      numerator 乘以denominator,然后将结果之和除以denominator 之和:

      outcome = numerator.mul(denominator, level=0, axis=1).sum(1)
      outcome = outcome.div(denominator.sum(1))
      df.assign(WA = outcome)
      
            A  A_Weight     B  B_weights     C  C_weights     D  D_weights           WA
      0  2000        37  2100         17  2500          5     0          0  2071.186441
      1  1000        47  1500         21  1400         35  1600         32  1323.703704
      2  2509        33  2000          6     0          0  2100         10  2363.204082
      3  2145        16  1600          2  2300         40  2000          5  2214.603175
      
      

      【讨论】:

        猜你喜欢
        • 2016-05-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-06
        • 2021-06-26
        • 2018-05-23
        相关资源
        最近更新 更多