【问题标题】:How to do a complex Groupyby in pandas?如何在 pandas 中进行复杂的 Group By?
【发布时间】:2017-10-17 07:21:45
【问题描述】:

我有一个 pandas 数据框,例如:

      a    b   id
1    10    6    1
2     6   -3    1
3    -3   12    1  # id is 1, but needs a tie breaker
4    -2   12    1  # id is 1, but needs a tie breaker
5     4    8    2 
6    12   11    2  
7     3   -5    2
8     3   -5    2

如何创建一个新的数据框,它首先采用 id 列,然后在每次 b 列超过 10 时获取,如果有多行满足此条件,则通过选择a 列中最小值的行:

      a    b   id
1    -3   12    1 
2    12   11    2 

我有一个包含大约 2,000,000 行和大约 10,000 个 id 值的数据框,因此 for 循环非常慢。

【问题讨论】:

    标签: python pandas numpy group-by


    【解决方案1】:

    这是一种解决方案,如果 df 是您的原始 DataFrame:

    df2 = df[df['b'] > 10]
    out = df2.loc[df2.groupby('id')['a'].idxmin()]
    

    你应该得到:

        a   b  id
    3  -3  12   1
    6  12  11   2
    

    【讨论】:

    • 我不这样做,因为min 必须应用于特定列而不是所有列。如果可以使用df.min('a') 进行选择,那将起作用。
    【解决方案2】:

    您可以根据 id 进行分组并应用查询 b>10 并查找最小值 a 的函数。见下文

    def my_func(group):
        return df.ix[group.query('b>10')['a'].argmin(), ['a','b']]
    
    print df.groupby(['id']).apply(my_func).reset_index()
    

    这会导致

      id   a   b
    0   1  -3  12
    1   2  12  11
    

    【讨论】:

      【解决方案3】:
      >>> data = pd.DataFrame({'a': [10, 6, -3, -2, 4, 12, 3, 3], 
      'b': [6, -3, 12, 12, 8, 11, -5, -5], 
      'id': [1, 1, 1, 1, 2, 2, 2, 2]})
      

      编写一个函数,根据b 的条件过滤DataFrame,然后使用idxmin 获取a 最小的索引。然后我们将此函数应用于分组数据。

      >>> def get_rows(data):
          ...     return data.loc[data.loc[data['b'] > 10].a.idxmin()]
      
      >>> data.groupby('id').apply(get_rows)
           a   b  id
      id            
      1   -3  12   1
      2   12  11   2
      

      【讨论】:

        【解决方案4】:

        这是另一个解决方案:

        data = {'a': [10,6,-3,-2,4,12,3,3], 'b': [6,-3,12,12,8,11,-5,-5], 'id': [1,1,1,1,2,2,2,2]}
        df = pandas.DataFrame.from_dict(data)
        grouper = df[df.b > 10].groupby(df.id)
        filtered = list()
        for group, group_data in grouper:
            filtered.append(group_data.apply(min))
        df_filtered = pandas.DataFrame.from_records(filtered)
        
        # output
            a   b  id
        0  -3  12   1
        1  12  11   2
        

        注意:在这种情况下,您的结果索引将为 [0, 1]。

        【讨论】:

          猜你喜欢
          • 2016-04-17
          • 1970-01-01
          • 1970-01-01
          • 2018-03-05
          • 1970-01-01
          • 2012-09-08
          • 2011-10-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多