获取 groupby 中的第一个和最后一个值

Posted

技术标签:

【中文标题】获取 groupby 中的第一个和最后一个值【英文标题】:get first and last values in a groupby 【发布时间】:2016-12-12 08:14:50 【问题描述】:

我有一个数据框df

df = pd.DataFrame(np.arange(20).reshape(10, -1),
                  [['a', 'a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'd'],
                   ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']],
                  ['X', 'Y'])

如何获取按第一级索引分组的第一行和最后一行?

我试过了

df.groupby(level=0).agg(['first', 'last']).stack()

得到了

          X   Y
a first   0   1
  last    6   7
b first   8   9
  last   12  13
c first  14  15
  last   16  17
d first  18  19
  last   18  19

这与我想要的非常接近。我怎样才能保留 1 级索引并获得它:

      X   Y
a a   0   1
  d   6   7
b e   8   9
  g  12  13
c h  14  15
  i  16  17
d j  18  19
  j  18  19

【问题讨论】:

【参考方案1】:

选项 1

def first_last(df):
    return df.ix[[0, -1]]

df.groupby(level=0, group_keys=False).apply(first_last)


选项 2 - 仅在索引唯一时有效

idx = df.index.to_series().groupby(level=0).agg(['first', 'last']).stack()
df.loc[idx]

选项 3 - 根据下面的注释,这仅在没有 NA 时才有意义

我还滥用了agg 功能。下面的代码可以工作,但丑得多。

df.reset_index(1).groupby(level=0).agg(['first', 'last']).stack() \
    .set_index('level_1', append=True).reset_index(1, drop=True) \
    .rename_axis([None, None])

注意

per @unutbu:agg(['first', 'last']) 取第一个非 na 值。

我将此解释为,必须逐列运行此列。此外,强制 index level=1 对齐可能甚至没有意义。

让我们加入另一个测试

df = pd.DataFrame(np.arange(20).reshape(10, -1),
                  [list('aaaabbbccd'),
                   list('abcdefghij')],
                  list('XY'))

df.loc[tuple('aa'), 'X'] = np.nan

def first_last(df):
    return df.ix[[0, -1]]

df.groupby(level=0, group_keys=False).apply(first_last)

df.reset_index(1).groupby(level=0).agg(['first', 'last']).stack() \
    .set_index('level_1', append=True).reset_index(1, drop=True) \
    .rename_axis([None, None])

果然!第二种解决方案是采用 X 列中的第一个有效值。现在强制该值与索引 a 对齐是荒谬的。

【讨论】:

虽然看起来更复杂,但当有很多组时,reset_index/agg 解决方案明显比groupby/apply 解决方案快。例如,当df = pd.DataFrame(np.random.randint(100, size=(10**3,4)), columns=list('ABCD')).set_index(['A','B']).rename_axis([None, None]). 不错的解决方案!还可能需要注意 agg(['first', 'last']) 返回第一个和最后一个非 NaN 值(如果可用)。 apply(first_last) 将返回第一个和最后一个值,即使它们是 NaN。 我认为对于最新的熊猫版本,我们需要 df.iloc 而不是 df.ix 参见例如***.com/questions/59991397/…【参考方案2】:

这可能是一个简单的解决方案。

df.groupby(level = 0, as_index= False).nth([0,-1])

      X   Y
a a   0   1
  d   6   7
b e   8   9
  g  12  13
c h  14  15
  i  16  17
d j  18  19

希望这会有所帮助。 (Y)

【讨论】:

【参考方案3】:

请试试这个:

对于最后一个值:df.groupby('Column_name').nth(-1)

对于第一个值:df.groupby('Column_name').nth(0)

【讨论】:

以上是关于获取 groupby 中的第一个和最后一个值的主要内容,如果未能解决你的问题,请参考以下文章

pandas使用groupby.first函数groupby.nth函数获取每个组中的第一个值实战:groupby.first函数和groupby.nth函数对比(对待NaN的差异)

获取下拉框第一个选项的值最后一个选项的值第二个选项的值

获取数组中的第一个和最后一个元素

如何在java中获取数组中的第一个和最后一个元素?

获取 groupBy 中的最后一项

groupby pandas中的原始索引列