【问题标题】:reduce a panda dataframe by groups按组减少熊猫数据框
【发布时间】:2018-06-21 19:34:41
【问题描述】:

我一直在广泛搜索,但无法解决这个问题:

我在 pandas 中有一个如下所示的数据框:

date    ticker Name NoShares SharePrice Volume Relation
2/1/10  aaa    zzz  1        1          1      d 
2/1/10  aaa    yyy  1        2          5      o
2/1/10  aaa    zzz  2        5          2      d  
2/5/10  bbb    xxx  5        5          1      do
2/5/10  ccc    www  5        5          1      d
2/5/10  ccc    www  5        5          1      d
2/5/10  ddd    vvv  5        5          1      o
2/6/10  aaa    zzz  1        1          3      d

要求

  1. 我想按日期和姓名分组,并且:
  2. 有总股数
  3. 有一个股票价格的加权平均列(权重是 NoShares)
  4. 平均体积并将其作为一列
  5. 保持关系不变

所以我的输出应该是这样的:

date    ticker Name NoShares SharePrice Volume Relation
2/1/10  aaa    zzz  3        3.6        1      d 
2/1/10  aaa    yyy  1        2          5      o
2/5/10  bbb    xxx  5        5          1      do
2/5/10  ccc    www  10       5          1      d
2/5/10  ddd    vvv  5        5          1      o
2/6/10  aaa    zzz  1        1          3      d

我尝试了有关堆栈溢出的文档和其他答案,但似乎无法正确解决。感谢帮助。干杯。

【问题讨论】:

    标签: python pandas group-by


    【解决方案1】:

    这是我的解决方案:

    grpby = df.groupby(['date','Name'])
    a = grpby.apply(lambda x: np.average(a = x['SharePrice'],weights=x['NoShares'])).to_frame(name='SharePrice')
    b = grpby.agg({'NoShares':'sum','Volume':'mean','Relation':'max'})
    print b.join(a)
    
                 Volume Relation  NoShares  SharePrice
    date   Name                                       
    2/1/10 yyy   5.0000        o         1      2.0000
           zzz   1.5000        d         3      3.6667
    2/5/10 vvv   1.0000        o         5      5.0000
           www   1.0000        d        10      5.0000
           xxx   1.0000       do         5      5.0000
    2/6/10 zzz   3.0000        d         1      1.0000
    

    之后只需 reset_index()。

    【讨论】:

    • 创建lambda后可以跳过join直接聚合:weigted_mean = lambda x: np.average(x, weights=tdf.loc[x.index, "NoShares"]) tdf.groupby(['date','Name']).agg({'NoShares':'sum','SharePrice': weigted_mean, 'Volume': 'mean'}).reset_index()
    • 很好的技术可以让这一切都发生在一个 .agg() 调用中。请注意它会创建与 tdf 的耦合。
    • 谢谢。答案得到了很好的解释并且非常有帮助(当然可以准确地解决我的问题)。
    【解决方案2】:

    我在这里做了一个假设。当您说按日期和名称分组并保持关系时-我假设股票代码和关系对于这些组也是唯一的。因此,为简单起见,我将所有 4 个分组。

    df = pd.DataFrame([
                    ['2/1/10', 'aaa', 'zzz', 1, 1, 1, 'd'], 
                    ['2/1/10', 'aaa', 'yyy', 1, 2, 5, 'o'],
                    ['2/1/10', 'aaa', 'zzz', 2, 5, 2, 'd'],  
                    ['2/5/10', 'bbb', 'xxx', 5, 5, 1, 'do'],
                    ['2/5/10', 'ccc', 'www', 5, 5, 1, 'd'],
                    ['2/5/10', 'ccc', 'www', 5, 5, 1, 'd'],
                    ['2/5/10', 'ddd', 'vvv', 5, 5, 1, 'o'],
                    ['2/6/10', 'aaa', 'zzz', 1, 1, 3, 'd']],
                 columns = ['date', 'ticker', 'Name', 'NoShares',
                            'SharePrice', 'Volume', 'Relation'])
    
    def process_date(dg):
        return pd.DataFrame([[
                            dg['NoShares'].sum(),
                            (dg['NoShares'] * dg['SharePrice']).sum() / dg['NoShares'].sum(),
                            dg['Volume'].mean(),
                            ]], columns=['NoShares', 'SharePrice', 'Volume'])
    
    df.groupby(['date', 'ticker', 'Name', 'Relation']).apply(process_date).reset_index(4, drop=True).reset_index(drop=False)
    

    结果:

         date ticker Name Relation  NoShares  SharePrice  Volume
    0  2/1/10    aaa  yyy        o         1    2.000000     5.0
    1  2/1/10    aaa  zzz        d         3    3.666667     1.5
    2  2/5/10    bbb  xxx       do         5    5.000000     1.0
    3  2/5/10    ccc  www        d        10    5.000000     1.0
    4  2/5/10    ddd  vvv        o         5    5.000000     1.0
    5  2/6/10    aaa  zzz        d         1    1.000000     3.0
    

    【讨论】:

    • 谢谢。如果可以的话,也会将此标记为已接受的答案。你的假设是正确的。
    【解决方案3】:

    Dickster 和 Leo 的答案都很好,但请注意 .groupby 默认设置了 dropna=True。因此,如果您有一个数据集并在多个列上执行groupby,其中一些列可能包含NaN's,Pandas 将删除这些组。最终的 DataFrame 将有更少的行。

    SQL Server 上的同一 SQL 查询不会删除 group by 子句中的列中具有 NULL 值的行。我不知道这是否适用于其他 RDBMS,但请记住,Pandas 默认以不同的方式处理 group by

    【讨论】:

      猜你喜欢
      • 2015-11-10
      • 2018-05-26
      • 2013-12-10
      • 1970-01-01
      • 2013-02-28
      • 1970-01-01
      • 2019-10-14
      • 1970-01-01
      相关资源
      最近更新 更多