Python 分组并删除熊猫中的配对记录
我有一个这样的数据框Python 分组并删除熊猫中的配对记录,python,pandas,Python,Pandas,我有一个这样的数据框 col1 col2 col3 col4 a1 b1 c1 + a1 b1 c1 + a1 b2 c2 + a1 b2 c2 - a1 b2 c2 + 如果在col1、col2和col3中有两个值相同的记录,并且在col4中有相反的符号,则应将它们从数据帧中删除 输出: col1 col2 col
col1 col2 col3 col4
a1 b1 c1 +
a1 b1 c1 +
a1 b2 c2 +
a1 b2 c2 -
a1 b2 c2 +
如果在col1
、col2
和col3
中有两个值相同的记录,并且在col4
中有相反的符号,则应将它们从数据帧中删除
输出:
col1 col2 col3 col4
a1 b1 c1 +
a1 b1 c1 +
a1 b2 c2 +
col1 col2 col3 col4
0 a1 b1 c1 +
1 a1 b1 c1 +
4 a1 b2 c2 +
col1 col2 col3 col4
0 a1 b1 c1 +
1 a1 b1 c1 +
4 a1 b2 c2 +
11 a1 b3 c3 +
12 a1 b3 c3 +
到目前为止,我尝试了pandasduplicated
和groupby
,但没有找到配对。如何做到这一点?我认为需要对计数组定义所有4
列,然后使用helperSeries
再次分组定义+-
组并与集进行比较:
s = df.groupby(['col1','col2','col3', 'col4']).cumcount()
df = df[~df.groupby(['col1','col2','col3', s])['col4']
.transform(lambda x: set(x) == set(['+','-']))]
print (df)
col1 col2 col3 col4
0 a1 b1 c1 +
1 a1 b1 c1 +
6 a1 b2 c2 +
为了更好地理解,请创建新列:
df['help'] = df.groupby(['col1','col2','col3', 'col4']).cumcount()
print (df)
col1 col2 col3 col4 help
0 a1 b1 c1 + 0
1 a1 b1 c1 + 1
2 a1 b2 c2 + 0
3 a1 b2 c2 - 0
4 a1 b2 c2 + 1
df = df[~df.groupby(['col1','col2','col3', 'help'])['col4']
.transform(lambda x: set(x) == set(['+','-']))]
print (df)
col1 col2 col3 col4 help
0 a1 b1 c1 + 0
1 a1 b1 c1 + 1
4 a1 b2 c2 + 1
考虑到“如果有两条记录在col1、col2和col3中具有相同的值,并且在col4中具有相反的符号,则应将其从数据帧中删除”的评论,则:
1) 识别并删除重复项:df.drop_duplicates()
2) 按前三列对它们进行分组:df.groupby(['col1','col2','col3'])
3) 只保留大小为1的组(否则,这意味着我们有“+”和“-”)两个:.filter(lambda组:len(group)==1)
一应俱全:
df.drop_duplicates().groupby(['col1','col2','col3']).filter(lambda g:len(g)==1)
首先,按col1
,col2
和col3
对数据帧进行分组。然后,应用方法,该方法将减去组中在col4
中具有不同符号的行
在此方法中,将col4
,+
的值替换为1,将-
的值替换为-1。然后对col4
中的值求和(让我们调用变量,它使该和保持有符号行计数)。只有两种可能的结果,要么是+
行占主导地位(正和值),要么是-
行占主导地位(负和值)。因此,您可以返回新的数据帧,带有signed_row_count
sign-incol4
的行数,或者signed_row_count
sign-incol4
的行数,具体取决于总和的符号
以下是代码:
df = pd.DataFrame(
[['a1', 'b1', 'c1', '+'], ['a1', 'b1', 'c1', '+'], ['a1', 'b2', 'c2', '+'], ['a1', 'b2', 'c2', '-'], ['a1', 'b2', 'c2', '+']],
columns=['col1', 'col2', 'col3', 'col4']
)
print(df)
# col1 col2 col3 col4
# 0 a1 b1 c1 +
# 1 a1 b1 c1 +
# 2 a1 b2 c2 +
# 3 a1 b2 c2 -
# 4 a1 b2 c2 +
def subtract_rows(df):
signed_row_count = df['col4'].replace({'+': 1, '-': -1}).sum()
if signed_row_count >= 0:
result = pd.DataFrame([df.iloc[0][['col1', 'col2', 'col3']].tolist() + ['+']] * signed_row_count, columns=df.columns)
else:
result = pd.DataFrame([df.iloc[0][['col1', 'col2', 'col3']].tolist() + ['-']] * abs(signed_row_count), columns=df.columns)
return result
reduced_df = (df.groupby(['col1', 'col2', 'col3'])
.apply(subtract_rows)
.reset_index(drop=True))
print(reduced_df)
# col1 col2 col3 col4
# 0 a1 b1 c1 +
# 1 a1 b1 c1 +
# 2 a1 b2 c2 +
以下是我的尝试:
df[df.assign(ident=df.assign(count=df.col4.eq('+').astype(int))\
.groupby(['col1','col2','col3','count']).cumcount())\
.groupby(['col1','col2','col3','ident']).transform(lambda x: len(x) < 2)['col4']]
在更稳健的测试集上:
df = pd.DataFrame(
[['a1', 'b1', 'c1', '+'], ['a1', 'b1', 'c1', '+'], ['a1', 'b2', 'c2', '+'], ['a1', 'b2', 'c2', '-'], ['a1', 'b2', 'c2', '+'],
['a1','b3','c3','+'],['a1','b3','c3','-'],['a1','b3','c3','-'],['a1','b3','c3','-'],['a1','b3','c3','+'],['a1','b3','c3','+'],['a1','b3','c3','+'],['a1','b3','c3','+']],
columns=['col1', 'col2', 'col3', 'col4']
)
输入数据帧:
col1 col2 col3 col4
0 a1 b1 c1 +
1 a1 b1 c1 +
2 a1 b2 c2 +
3 a1 b2 c2 -
4 a1 b2 c2 +
5 a1 b3 c3 +
6 a1 b3 c3 -
7 a1 b3 c3 -
8 a1 b3 c3 -
9 a1 b3 c3 +
10 a1 b3 c3 +
11 a1 b3 c3 +
12 a1 b3 c3 +
df[df.assign(ident=df.assign(count=df.col4.eq('+').astype(int))\
.groupby(['col1','col2','col3','count']).cumcount())\
.groupby(['col1','col2','col3','ident']).transform(lambda x: len(x) < 2)['col4']]
如果是成对的(+、-),你想一直保留“+”、“-”还是你不在乎?@Guybrush-它可以是任何字符串来替换+,-你编辑了你的问题,现在我很困惑:你到底想做什么?如果存在(a,b,c,-)行,则删除(a,b,c,d)?@GYBRUSH-如果有两条记录在col1,col2和col3中具有相同的值,并且在col4中具有相反的符号,则应将它们从DataFrame中删除。如果负号始终在a+之前和之后。如果您有(+--+++)您想删除所有对的左(+)还是只删除正左(-++)旁边的对?我认为您需要更广泛的测试集和预期的输出。我想在col1、col2、col3中找到重复项,只有在这之后,如果找到成对项,我需要删除记录。我的预期输出与您的不一样answer@MohamedThasinah-因此,对于每个组,需要删除+/-
对吗?如果找到+/-对,则删除它。或者保持原样。例如,如果一组中+符号包含5次,而-symbol包含4次,则应删除4对,并保留一个+符号same@MohamedThasinah-你是对的,答案被改变了。