python - 如何从满足多个条件的数据框中删除特定行(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)
推荐阅读
- sas - 用途:在SAS中读取多条记录时
- assembly - GDB 的 x memory-dump 命令中的十六进制大小
- mysql - SQL 无法连接到数据库服务器
- javascript - 如何在 itext 5 中使用按钮作为图像字段
- java - 基于选择的 AuthProvider Spring Security
- xaml - 从 XAML 清除 calendarDatePicker 控件中的选取日期
- database - Flutter:共享偏好或范围模型以提高速度
- c++11 - 可以在函数声明中使用“auto”吗?
- javascript - Chai - 期望一个对象具有数组忽略顺序的深层属性
- python - 神经网络和遗传算法