【问题标题】:Pandas groupby is duplicating groups when using apply twicePandas groupby 使用两次应用时会复制组
【发布时间】:2020-05-10 09:15:02
【问题描述】:

pandas groupby 可以使用groupby.apply(func) 并在func 内部使用.apply() 的另一个实例而不复制和覆盖数据吗?

在某种程度上,.apply() 的使用是嵌套的。

Python 3.7.3 pandas==0.25.1

import pandas as pd


def dummy_func_nested(row):
    row['new_col_2'] = row['value'] * -1
    return row


def dummy_func(df_group):
    df_group['new_col_1'] = None

    # apply dummy_func_nested
    df_group = df_group.apply(dummy_func_nested, axis=1)

    return df_group


def pandas_groupby():
    # initialize data
    df = pd.DataFrame([
        {'country': 'US', 'value': 100.00, 'id': 'a'},
        {'country': 'US', 'value': 95.00, 'id': 'b'},
        {'country': 'CA', 'value': 56.00, 'id': 'y'},
        {'country': 'CA', 'value': 40.00, 'id': 'z'},
    ])

    # group by country and apply first dummy_func
    new_df = df.groupby('country').apply(dummy_func)

    # new_df and df should have the same list of countries
    assert new_df['country'].tolist() == df['country'].tolist()
    print(df)


if __name__ == '__main__':
    pandas_groupby()

上面的代码应该返回

  country  value id new_col_1  new_col_2
0      US  100.0  a      None     -100.0
1      US   95.0  b      None      -95.0
2      CA   56.0  y      None      -56.0
3      CA   40.0  z      None      -40.0

但是,代码返回

  country  value id new_col_1  new_col_2
0      US  100.0  a      None     -100.0
1      US   95.0  a      None      -95.0
2      US   56.0  a      None      -56.0
3      US   40.0  a      None      -40.0

仅当两个组的行数相等时才会出现此行为。如果一组有更多行,则输出如预期。

【问题讨论】:

    标签: python pandas duplicates pandas-groupby apply


    【解决方案1】:

    在使用 groupby 时,我们应该避免在使用 apply() 的函数中使用 apply() 方法

    产生所需结果的正确代码如下。

    免责声明:可以更有效地编写代码。目的是为了证明我们应该避免在groupby.apply() 内部调用apply() 方法。如果我们应用它的组在每个组中具有相同数量的行,则会产生不利影响。如果每组中的行数不相等,则一切顺利。同样,这只发生在组具有相同数量的行时。

    致用户:u10-forward

    import pandas as pd
    
    
    def dummy_func_nested(df):
        df['new_col_2'] = df['value'] * -1
        return df
    
    
    def dummy_func(df_group):
        df_group['new_col_1'] = None
    
        # apply dummy_func_nested
        df_group = dummy_func_nested(df_group)
    
        return df_group
    
    
    def pandas_groupby():
        # initialize data
        df = pd.DataFrame([
            {'country': 'US', 'value': 100.00, 'id': 'a'},
            {'country': 'US', 'value': 95.00, 'id': 'b'},
            {'country': 'CA', 'value': 56.00, 'id': 'y'},
            {'country': 'CA', 'value': 40.00, 'id': 'z'},
        ])
    
        # group by country and apply first dummy_func
        new_df = df.groupby('country').apply(dummy_func)
    
        # new_df and df should have the same list of countries
        assert new_df['country'].tolist() == df['country'].tolist()
        print(df)
    
    
    if __name__ == '__main__':
        pandas_groupby()
    

    也就是说,我仍然认为这是一个错误,无法在 groupby.apply() 中调用 apply() 方法。

    【讨论】:

      【解决方案2】:

      引用documentation:

      在当前实现中,apply 在第一列/行上调用 func 两次,以决定它是否可以采用快速或慢速代码路径。如果 func 有副作用,这可能会导致意外行为,因为它们会对第一列/行生效两次。

      尝试在您的代码中更改以下代码:

      def dummy_func(df_group):
          df_group['new_col_1'] = None
      
          # apply dummy_func_nested
          df_group = df_group.apply(dummy_func_nested, axis=1)
      
          return df_group
      

      收件人:

      def dummy_func(df_group):
          df_group['new_col_1'] = None
      
          # apply dummy_func_nested
          df_group = dummy_func_nested(df_group)
      
          return df_group
      

      您不需要apply

      当然,更有效的方法是:

      df['new_col_1'] = None
      df['new_col_2'] = -df['value']
      print(df)
      

      或者:

      print(df.assign(new_col_1=None, new_col_2=-df['value']))
      

      【讨论】:

      • 我记得在文档中读到过,然后马上就忘记了,很好!
      • 使用dummy_func_nested(df_group) 而不是df_group.apply(dummy_func_nested, axis=1) 会导致此输出gist.github.com/olehdubno/0bc25b11c1efe3dd83b955a39f2422f7 输出显示原始组,但行仍被另一个组的副本覆盖。
      • 我运行了代码,似乎得到了您想要的输出,但似乎无法重现您的输出。你在做什么来得到那个输出?
      • 使用独立于apply()dummy_func_nested(),即df_group = dummy_func_nested(df_group),会产生所需的结果。不知道我跑了什么导致框架以一种奇怪的方式显示。我的理解是,我们不应该在使用 groupby 的其他 apply() 方法中调用 apply() 方法。我们应该直接应用函数而不是使用apply。
      • @OlehDubno 请接受并支持它的工作原理:-)
      猜你喜欢
      • 2015-08-18
      • 2019-08-26
      • 2020-09-17
      • 1970-01-01
      • 1970-01-01
      • 2015-08-03
      • 2019-09-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多