【问题标题】:How to apply "first" and "last" functions to columns while using group by in pandas?在 Pandas 中使用 group by 时如何将“first”和“last”函数应用于列?
【发布时间】:2013-02-06 17:11:57
【问题描述】:

我有一个数据框,我想按特定列(或者换句话说,按特定列中的值)对它进行分组。我可以通过以下方式做到这一点:grouped = df.groupby(['ColumnName']).

我把这个操作的结果想象成一个表格,其中一些单元格可以包含一组值而不是单个值。为了得到一个普通的表格(即每个单元格只包含一个值的表格),我需要指出我想使用什么函数将单元格中的值集转换为单个值。

例如,我可以将一组值替换为它们的总和,或者它们的最小值或最大值。我可以通过以下方式做到这一点:grouped.sum()grouped.min() 等等。

现在我想对不同的列使用不同的函数。我发现我可以通过以下方式做到这一点:grouped.agg({'ColumnName1':sum, 'ColumnName2':min}).

但是,由于某些原因,我无法使用first。更详细地说,grouped.first() 有效,但 grouped.agg({'ColumnName1':first, 'ColumnName2':first}) 无效。结果我得到一个 NameError:NameError: name 'first' is not defined。所以,我的问题是:为什么会发生以及如何解决这个问题。

添加

Here我找到了下面的例子:

grouped['D'].agg({'result1' : np.sum, 'result2' : np.mean})

可能我还需要使用np?但在我的情况下,python 无法识别“np”。我应该导入它吗?

【问题讨论】:

  • 您不需要np,它可以与普通的旧sum 一起使用(只是效率较低)。 numpy 是用 pandas 导入的(如果你 import pandas as pdpd.np),但为了方便,大多数人也会单独导入它。

标签: python pandas group-by


【解决方案1】:
c_df = b_df.groupby('time').agg(first_x=('x', lambda x: list(x)[0]),
                                last_x=('x', lambda x: list(x)[-1]),
                                last_y=('y', lambda x: list(x)[-1]))

【讨论】:

    【解决方案2】:

    我会使用如下所示的自定义聚合器。

    d = pd.DataFrame([[1,"man"], [1, "woman"], [1, "girl"], [2,"man"], [2, "woman"]],columns = 'number family'.split())
    d
    

    这是输出:

        number family
     0       1    man
     1       1  woman
     2       1   girl
     3       2    man
     4       2  woman
    

    现在聚合采用第一个和最后一个元素。

    d.groupby(by = "number").agg(firstFamily= ('family', lambda x: list(x)[0]), lastFamily =('family', lambda x: list(x)[-1]))
    

    这个聚合的输出如下所示。

           firstFamily lastFamily
    number                       
    1              man       girl
    2              man      woman
    

    我希望这会有所帮助。

    【讨论】:

      【解决方案3】:

      不要使用firstlast,而是在agg 方法中使用它们的字符串表示。例如关于 OP 的案例:

      grouped = df.groupby(['ColumnName'])
      grouped['D'].agg({'result1' : np.sum, 'result2' : np.mean})
      
      #you can do the string representation for first and last
      grouped['D'].agg({'result1' : 'first', 'result2' : 'last'})
      

      【讨论】:

      • 这是解决此问题的最新方法。
      • 有没有办法将 kwarg 也传递给函数,例如numeric_only=True?
      【解决方案4】:

      我认为问题在于有两种不同的first 方法,它们共享一个名称但行为不同,一种是用于groupby objectsanother for a Series/DataFrame(与时间序列有关)。

      要使用 agg 在 DataFrame 上复制 groupby first 方法的行为,您可以使用 iloc[0](按索引获取每个组(DataFrame/Series)中的第一行):

      grouped.agg(lambda x: x.iloc[0])
      

      例如:

      In [1]: df = pd.DataFrame([[1, 2], [3, 4]])
      
      In [2]: g = df.groupby(0)
      
      In [3]: g.first()
      Out[3]: 
         1
      0   
      1  2
      3  4
      
      In [4]: g.agg(lambda x: x.iloc[0])
      Out[4]: 
         1
      0   
      1  2
      3  4
      

      类似地,您可以使用iloc[-1] 复制last

      注意:这将按列工作,等等:

      g.agg({1: lambda x: x.iloc[0]})
      

      在旧版本的 pandas 中,您可以使用 irow 方法(例如 x.irow(0),请参阅以前的编辑。


      一些更新的笔记:

      最好使用nth groupby 方法完成,该方法要快得多 >=0.13:

      g.nth(0)  # first
      g.nth(-1)  # last
      

      您必须小心一点,因为 firstlast 的默认行为会忽略 NaN 行...而 IIRC 对于 DataFrame groupbys 它在 0.13 之前被破坏...有一个 @987654340 nth 的 @ 选项。

      您可以使用字符串而不是内置函数(尽管 IIRC pandas 发现它是 sum 内置函数并应用 np.sum):

      grouped['D'].agg({'result1' : "sum", 'result2' : "mean"})
      

      【讨论】:

      • 以防万一它对任何人有用,根据the docsirow 现在已被弃用(x.iloc[0] 可以代替)
      • @cd98 感谢您指出这一点,我已经用更新的语法更新了这个:)
      • 我对@9​​87654325@ 感到困惑;它指出:Aggregating functions are ones that reduce the dimension of the returned objects, for example: mean, sum, size, count, std, var, sem, describe, first, last, nth, min, max. 那么他们在说什么?
      • 在某种意义上这里有三种类型的映射:聚合、应用和过滤(上面是一种过滤器,虽然它使用了 agg 动词)。这很复杂,您可以使用 either agg 或 apply 来完成 .iloc[0] 工作,不知道我为什么使用 agg,apply 可能是一个更好的描述。由于这篇文章我修复了 nth 以更好地工作,所以 IMO 这是这里的首选解决方案。
      【解决方案5】:

      我不确定这是否真的是问题,但 summin 是 Python 内置函数,它们将一些迭代作为输入,而 first 是 pandas Series 对象的一种方法,所以也许是不在您的命名空间中。此外,它需要其他东西作为输入(文档说一些偏移值)。

      我想解决它的一种方法是创建自己的 first 函数,并将其定义为将 Series 对象作为输入,例如:

      def first(Series, offset):
          return Series.first(offset)
      

      或类似的东西..

      【讨论】:

        猜你喜欢
        • 2018-07-05
        • 2012-04-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多