简体   繁体   English

如何根据条件从数据框中删除行

[英]How to delete rows from dataframe based on condition

I have the following dataframe with ("ID", "Month" and "status").我有以下数据框(“ID”、“月”和“状态”)。 Status is regarding "Churn"= 1 and 'Not Churn" = 2. I want to delete all rows for ID's who are already churned except the first appearance. For example:状态是关于“Churn”= 1 和“Not Churn”= 2。我想删除除第一次出现之外已经被搅动的 ID 的所有行。例如:

Dataframe数据框

    ID      Month   Status
    2310    201708  2
    2310    201709  2
    2310    201710  1
    2310    201711  1
    2310    201712  1
    2310    201801  1
    2311    201704  2
    2311    201705  2
    2311    201706  2
    2311    201707  2
    2311    201708  2
    2311    201709  2
    2311    201710  1
    2311    201711  1
    2311    201712  1
    2312    201708  2
    2312    201709  2
    2312    201710  2
    2312    201711  1
    2312    201712  1
    2312    201801  1

After deleting I should have the following dataframe删除后我应该有以下数据框

    ID      Month   Status
    2310    201708  2
    2310    201709  2
    2310    201710  1

    2311    201704  2
    2311    201705  2
    2311    201706  2
    2311    201707  2
    2311    201708  2
    2311    201709  2
    2311    201710  1

    2312    201708  2
    2312    201709  2
    2312    201710  2
    2312    201711  1

I tried the following- first to find min date for each customer ID and status=1我尝试了以下 - 首先找到每个客户 ID 和 status=1 的最小日期

    df1=df[df.Status==1].groupby('ID')['Month'].min()

then I have to delete all rows for each ID with status 1 greater than min value for MOnth.然后我必须删除状态 1 大于 MOnth 最小值的每个 ID 的所有行。

If you're familiar with DataFrame.idxmin to get the indices of the elements of the most recent month, you could try:如果您熟悉DataFrame.idxmin来获取最近一个月的元素索引,您可以尝试:

# find minimum months
min_df = df.groupby(['ID','Status'])['Month'].idxmin().reset_index(drop=True)
# find indices of status 2 rows
df2 = df[df['Status'].eq(2)].index.to_series()
# append indices together
idx_df = min_df.append(df2).drop_duplicates()
# filter indices
df_new = df.iloc[idx_df].sort_index()

print(df_new)                                                                        
      ID   Month  Status
0   2310  201708       2
1   2310  201709       2
2   2310  201710       1
6   2311  201704       2
7   2311  201705       2
8   2311  201706       2
9   2311  201707       2
10  2311  201708       2
11  2311  201709       2
12  2311  201710       1
15  2312  201708       2
16  2312  201709       2
17  2312  201710       2
18  2312  201711       1

Update更新

Or, you may think about using GroupBy.apply :或者,您可能会考虑使用GroupBy.apply

df1 = df.groupby(['ID','Status']).apply(lambda x: (x['Status'].eq(2)) | (x['Month'].eq(x['Month'].min())))
df1 = df1.reset_index(level=['ID','Status'], drop=True)
df_new = df.loc[df1]

print(df_new)                                                                                                                                              
      ID   Month  Status
0   2310  201708       2
1   2310  201709       2
2   2310  201710       1
6   2311  201704       2
7   2311  201705       2
8   2311  201706       2
9   2311  201707       2
10  2311  201708       2
11  2311  201709       2
12  2311  201710       1
15  2312  201708       2
16  2312  201709       2
17  2312  201710       2
18  2312  201711       1

Update 2更新 2

However, if you're simply wanting to remove all of the status 1 rows that come after the row with the earliest month, then you could simply sort_values and transform :但是,如果您只是想删除最早月份的行之后的所有状态 1 行,那么您可以简单地sort_valuestransform

df = df.sort_values(by=['ID','Month']).reset_index(drop=True) 
df = df[df.groupby('ID')['Status'].transform(lambda x: ~(x.duplicated() & (x == 1)))]

print(df)                                                              
      ID   Month  Status
0   2310  201708       2
1   2310  201709       2
2   2310  201710       1
6   2311  201704       2
7   2311  201705       2
8   2311  201706       2
9   2311  201707       2
10  2311  201708       2
11  2311  201709       2
12  2311  201710       1
15  2312  201708       2
16  2312  201709       2
17  2312  201710       2
18  2312  201711       1

IIUC, you can use groupby with transform with boolean logic and then boolean indexing: IIUC,您可以使用groupby与布尔逻辑的transform ,然后使用布尔索引:

df[df.groupby('ID')['Status'].transform(lambda x: ~(x.duplicated() & (x == 1)))]

Output:输出:

      ID   Month  Status
0   2310  201708       2
1   2310  201709       2
2   2310  201710       1
6   2311  201704       2
7   2311  201705       2
8   2311  201706       2
9   2311  201707       2
10  2311  201708       2
11  2311  201709       2
12  2311  201710       1
15  2312  201708       2
16  2312  201709       2
17  2312  201710       2
18  2312  201711       1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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