繁体   English   中英

如何从满足多个条件的数据框中删除特定行(python pandas)?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM