假设我有一个如下所示的数据框:
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
列中的条目创建集合相结合,但未能产生任何甚至非常合理的内容。
答案 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()
。