![](/img/trans.png)
[英]How to keep the best row in a pandas dataframe satisfying multiple conditions with groupby
[英]How to remove specific rows from a dataframe satisfying multiple conditions (python pandas)?
我有以下数据帧:
id outcome
0 3 no
1 3 no
2 3 no
3 3 yes
4 3 no
5 5 no
6 5 no
7 5 yes
8 5 yes
9 6 no
10 6 no
11 6 yes
12 6 yes
13 6 yes
14 6 yes
15 6 yes
16 6 no
17 6 no
18 6 no
19 7 no
20 7 no
21 7 yes
22 7 yes
23 7 no
24 7 no
25 7 no
26 7 yes
它是根据 id 分组的。
我需要满足几个条件。
如果当前行之后的行具有相同的结果,我需要删除当前行。
如果一行是“是”,那么下一行必须是第一个“否”。
我还必须在“是”序列中包含最后一个“是”行。
此外,我还希望将最后一个“否”保持在“是”上方(因此“是”上方可能有 2 个“否”值:基本上是排在第一个和最后一个“否”的“否”行中)。
然后我需要删除作为最后一行的任何“是”行。
最后,如果 'id' 列只有一个 'no' 行,那么它也必须被删除。
这应该是输出。
id outcome
2 3 no
3 3 yes
4 3 no
10 6 no
15 6 yes
16 6 no
20 7 no
22 7 yes
23 7 no
25 7 no
26 7 yes
我目前正在这样做:
df = pd.DataFrame(data={'id':[3,3,3,3,3,5,5,5,5,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7],
'outcome': ['no','no','no','yes','no','no','no','yes','yes','no','no','yes','yes','yes','yes','yes','no','no','no', 'no', 'yes', 'no', 'no', 'yes']})
# part 1
g = df.groupby('id')['outcome']
m1 = g.shift().eq('yes') | g.shift(-1).eq('yes')
df = df[m1 & df.outcome.ne('yes') | (df.outcome.eq('yes') & g.shift().ne('yes') ) ]
# part 2
# The following removes any last rows that are a 'yes' per id
m2 = df.groupby(['id'])['outcome'].tail(1) != 'no'
df = df.drop(m2[m2].index)
#part 3
# The following removes any id counts that are one, as the last row 'yes' values should be removed, this would mean only 'no' rows are leftover
df_count = df.groupby(['id'])['outcome'].count().to_frame('count').reset_index()
df = pd.merge(df, df_count[['id','count']] , on=['id'], how='inner')
df = df.drop((df[df.count == 1].index))
但是,第 1 部分保留了第一个“是”值行,而不是我需要的最后一个“是”。
我也不确定第 2 部分和第 3 部分是否过于冗长,以及我是否可以做一些更精简的事情来满足上述所有条件。
所以我在我的代码的第 1 部分中使用了它,但它效率不高,并且需要很长时间才能运行。 这与快速执行(秒)的替代(但稍微不正确)答案相比。
值得一提的是,我在 70k 行上运行此代码。
index_to_remove = list()
data = df.groupby('id')['outcome'].apply(list).to_dict()
count = 0
for key,value in data.items():
for i in range(len(value)):
if i == len(value)-1:
count =count + 1
continue
if data[key][i] == "yes" and data[key][i+1] == "yes":
index_to_remove.append(count)
count =count + 1
continue
if i == 0 and data[key][i]=="no" and data[key][i+1] == "no":
index_to_remove.append(count)
count =count + 1
continue
elif data[key][i] == "no" and i == len(value) - 3:
if data[key][i+1] == "no" and data[key][i+2] == "no":
index_to_remove.append(count)
count =count + 1
continue
elif data[key][i] == "no" and i == len(value)-2:
if data[key][i+1] == "no":
index_to_remove.append(count)
count =count + 1
continue
elif data[key][i] == "no" and i == len(value)-1:
count =count + 1
continue
elif data[key][i] == "no" and data[key][i+1] == "no":
if data[key][i-1] == "no" or data[key][i+2] == "no":
index_to_remove.append(count)
count =count + 1
continue
count = count + 1
for index in index_to_remove:
df = df.drop(index)
print(df)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.