删除连续的重复项,同时保持最大值



我试图从X列中删除连续的重复项,同时根据Y列保留最大值的条目,但遗憾的是没有成功。数据帧如下:

32[/tr><1>
idx X Y
0 A
1 B
2 A 7
3 A 10
4 B
5 C 4
6 A 3
7 A 3

您需要应用itertools样式的groupby,然后保留Y最大的行。

>>> df 
idx  X   Y
0    0  A   3
1    1  B   2
2    2  A   7
3    3  A  10
4    4  B   1
5    5  C   4
6    6  A   3
7    7  A   5
>>> y_max = df.groupby(df['X'].ne(df['X'].shift()).cumsum())['Y'].transform('max')
>>> df[df['Y'] == y_max] 
idx  X   Y
0    0  A   3
1    1  B   2
3    3  A  10
4    4  B   1
5    5  C   4
7    7  A   5

编辑:

最初的解决方案有一个错误,只是偶然产生了正确的idx列。

编辑2:

如果你只想每组保留一行,你可以使用

>>> y_idxmax = df.groupby(df['X'].ne(df['X'].shift()).cumsum())['Y'].idxmax()
>>> df.loc[y_idxmax] 
idx  X   Y
0    0  A   3
1    1  B   2
3    3  A  10
4    4  B   1
5    5  C   4
7    7  A   5

这一点要归功于Ch3steR。

或者我宁愿只在groupby参数中指定组:

df.groupby(df['X'].ne(df['X'].shift()).cumsum(), as_index=False).max()

或者:

df.groupby(df['X'].ne(df['X'].shift()).cumsum()).max().reset_index(drop=True)

两种输出:

idx  X   Y
0    0  A   3
1    1  B   2
2    3  A  10
3    4  B   1
4    5  C   4
5    7  A   5

创建一列,将连续的数据堆到一个组中

df['temp']=(~(df['X']==df['X'].shift())|(df['X'].shift(-1)==df['X'])).cumsum()

一组接一组,并过滤掉其中Y的值等于每组中的最大值。放下温度柱

df[df.groupby('temp')['Y'].transform(lambda x:(x==x.max()))].drop(columns=['temp'])

更简洁的方法不是创建列,而是将连续的组保存到一个变量中,并按变量分组,如下所示

s=(~(df['X']==df['X'].shift())|(df['X'].shift(-1)==df['X'])).cumsum()
print(df[df.groupby(s)['Y'].transform(lambda x:(x==x.max()))])
idx  X   Y
0    0  A   3
1    1  B   2
3    3  A  10
4    4  B   1
5    5  C   4
7    7  A   5

我无法立即找出已经给出的答案,所以我写了一个简单的脚本来做同样的事情。它获取具有重复值的索引,并通过一次比较两个来删除它们。

检查以下代码-

import pandas as pd
data = {'X':['A', 'B', 'A', 'A', 'A', 'B', 'C', 'A', 'A'], 
'Y': [3, 2, 12, 7, 10, 1, 4, 3, 5]}
data = pd.DataFrame(data)
mask = data['X'] == data['X'].shift()
to_check = data.loc[mask].index.tolist()
for i, _ in enumerate(to_check):
index = to_check[i]
if data.iloc[index]['Y'] > data.iloc[index - 1]['Y']:
data.drop(index - 1, axis=0, inplace=True)
data.reset_index(inplace=True, drop=True)
else:
data.drop(index, axis=0, inplace=True)
data.reset_index(inplace=True, drop=True)
to_check = [value - 1 for value in to_check]
print(data)
# OUTPUT
X   Y
0  A   3
1  B   2
2  A  12
3  B   1
4  C   4
5  A   5

最新更新