从pandas dataframe中的组内部选择特定行

时间:2015-09-08 03:20:39

标签: python pandas indexing group-by dataframe

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

   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列中的条目创建集合相结合,但未能产生任何甚至非常合理的内容。

2 个答案:

答案 0 :(得分:3)

可以使用groupby并使用apply在每个组上运行一个简单的函数来完成此操作:

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

答案 1 :(得分:1)

这会更简单:

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()