从熊猫数据框中的组内选择特定行

Posted

技术标签:

【中文标题】从熊猫数据框中的组内选择特定行【英文标题】:Select particular rows from inside groups in pandas dataframe 【发布时间】:2015-12-03 14:32:20 【问题描述】:

假设我有一个如下所示的数据框:

   group  level
0      1     10
1      1     10
2      1     11
3      2      5
4      2      5
5      3      9
6      3      9
7      3      9
8      3      8

想要的输出是这样的:

   group  level
0      1     10
5      3      9

也就是说,这就是逻辑:查看每个组的内部,如果level 列中存在多个不同的值,则返回该组中的第一行。例如,没有选择组 2 中的任何行,因为 level 列中存在的唯一值是 5

另外,如果我想要最后一行而不是第一行这样的组,情况会如何变化?

我尝试将group_by 语句与从level 列中的条目创建集合相结合,但未能产生任何几乎合理的结果。

【问题讨论】:

【参考方案1】:

这可以通过groupbyapply 在每个组上运行一个简单的函数来完成:

def get_first_val(group):
    has_multiple_vals = len(group['level'].unique()) >= 2
    if has_multiple_vals:
        return group['level'].loc[group['level'].first_valid_index()]
    else:
        return None

df.groupby('group').apply(get_first_val).dropna()
Out[8]: 
group
1    10
3     9
dtype: float64

还有一个last_valid_index() 方法,所以你不必 进行任何重大更改以获取最后一行。

如果您想保留其他列,只需稍作调整:

import numpy as np
df['col1'] = np.random.randint(10, 20, 9)
df['col2'] = np.random.randint(20, 30, 9)
df
Out[17]: 
   group  level  col1  col2
0      1     10    19    21
1      1     10    18    24
2      1     11    14    23
3      2      5    14    26
4      2      5    10    22
5      3      9    13    27
6      3      9    16    20
7      3      9    18    26
8      3      8    11    2

def get_first_val_keep_cols(group):
    has_multiple_vals = len(group['level'].unique()) >= 2
    if has_multiple_vals:
        return group.loc[group['level'].first_valid_index(), :]
    else:
        return None

df.groupby('group').apply(get_first_val_keep_cols).dropna()
Out[20]: 
       group  level  col1  col2
group                          
1          1     10    19    21
3          3      9    13    27

【讨论】:

如何确保其他列得到维护,假设原始数据框有 col1、col2、col3,我仍希望将其保留为结果的一部分? 这神秘地不适用于我。使用以前的方法,我得到了正确的结果,只丢失了一些列,现在我得到了一个空的数据框。也许这里返回 group.loc[group['level'].first_valid_index(), :] without , ?【参考方案2】:

这样会更简单:

In [121]:

print df.groupby('group').\
          agg(lambda x: x.values[0] if (x.values!=x.values[0]).any() else np.nan).\
           dropna()

       level
group       
1         10
3          9

对于每个组,如果任何值与第一个值不同,则将该组聚合为其第一个值;否则,将其聚合到nan

最后,dropna()

【讨论】:

以上是关于从熊猫数据框中的组内选择特定行的主要内容,如果未能解决你的问题,请参考以下文章

从熊猫数据框中选择特定行

如何从熊猫数据框中的当前行中减去前一行并将其应用于每一行;不使用循环?

为排序的熊猫数据框中的每个 ID 选择特定列的第一个值

如何使用正则表达式从熊猫数据框中的一行中的字符串中提取所有特定值?

根据熊猫中多列中的值从数据框中选择行

根据熊猫中多列中的值从数据框中选择行