在 Python 中移除特定条件下的 ID

Removing IDs under specific conditions in Python

提问人:Coding_Nubie 提问时间:8/2/2023 最后编辑:Coding_Nubie 更新时间:8/2/2023 访问量:52

问:

我有一个数据集,我需要完全删除在特定日期之前及以后标记的 ID。我很难开始这个。

df =

 ID      Date        Flagged 
 101    6/4/2023       0
 101    7/23/2023      0
 102    4/28/2023      1
 102    5/2/2023       1
 102    6/30/2023      1
 102    7/11/2023      1
 103    6/23/2023      1
 103    7/12/2023      1
 104    4/17/2023      0 
 104    5/12/2023      1
 104    6/17/2023      1
 104    7/22/2023      1

我想一起删除 2023 年 5 月 1 日之前的所有 ID。 我试过了Flagged

today = datetime.datetime.today()
x_days = today - dt(days=90)`
filtered_df = df{(df['Flagged'] == 1) & (df['Date' >= x_days)]

当我运行它时,我仍然有我想完全删除的 ID。以下是所需的输出:

df =

 ID      Date      Flagged 
 103   6/23/2023     1
 103   7/12/2023     1
 104   5/12/2023     1
 104   6/17/2023     1
 104   7/22/2023     1

对此的任何帮助都很棒,谢谢!

python-3.x pandas dataframe 日期时间

评论

2赞 RomanPerekhrest 8/2/2023
你怎么能在输出中有条件?Flagged=0(df['Flagged'] == 1)
0赞 Coding_Nubie 8/2/2023
谢谢你发现我不是故意添加这些的,我会修复编辑的。
0赞 not_speshal 8/2/2023
@Coding_Nubie - 为什么删除 ID 101?
0赞 Michael S. 8/2/2023
为什么您想要的输出中没有 5-2-23?它既被标记,也没有出现在 5-1-23 之前
1赞 Coding_Nubie 8/2/2023
@MichaelS。因为他们在 5/1 之前标记了一条记录,所以我想一起忽略该 ID。

答:

1赞 Will 8/2/2023 #1

试试这个:

# Convert 'Date' column to datetime format (to be sure)
df['Date'] = pd.to_datetime(df['Date'])

# Define cutoff date
cutoff_date = datetime(2023, 5, 1)

# Create a mask to filter IDs flagged before the cutoff date
mask = (df['Flagged'] == 1) & (df['Date'] >= cutoff_date)

# Get the list of IDs to be removed
ids_to_remove = df.loc[mask, 'ID'].unique()

# Filter out the IDs from the DataFrame
filtered_df = df[~df['ID'].isin(ids_to_remove)]
0赞 not_speshal 8/2/2023 #2

使用布尔索引:

#convert to datetime if needed
df["Date"] = pd.to_datetime(df["Date"],format="%m/%d/%Y")

#get flagged IDs to ignore
flagged = df[df["Flagged"].eq(1)&df["Date"].lt(pd.Timestamp.today()-pd.DateOffset(90))]

>>> df[~df["ID"].isin(flagged["ID"])&df["Flagged"].eq(1)]

     ID       Date  Flagged
6   103 2023-06-23        1
7   103 2023-07-12        1
9   104 2023-05-12        1
10  104 2023-06-17        1
11  104 2023-07-22        1

评论

1赞 Michael S. 8/2/2023
小心这个答案。OP 希望在 2023 年 5 月 1 日之前标记所有日期,此答案取决于当前日期。如果 OP 在一个月后甚至几天后运行此代码,他们将无法获得所需的结果。
0赞 Coding_Nubie 8/2/2023
这似乎奏效了,谢谢
0赞 not_speshal 8/2/2023
@MichaelS - OP 在他们的帖子中使用了。 同样的逻辑。today - dt(days=90)
0赞 Michael S. 8/2/2023
是的,但 OP 指定了一个特定的日期,而不是从代码运行开始的特定时间。仅仅因为 OP 尝试并不意味着这是正确的方法。today - dt(days=90)
1赞 not_speshal 8/2/2023
@MichaelS。- 我认为 OP 想要一个动态解决方案。如果这是他们需要的,那么对日期进行硬编码很容易。
1赞 Michael S. 8/2/2023 #3

首先查找在指定日期之前标记的所有 ID,然后仅查找已标记且没有错误 ID 之一的值:

import pandas as pd
import datetime 

# create dataframe:
df = pd.DataFrame(
    {'ID' : [101, 101, 102, 102, 102, 102, 103, 103, 104, 104, 104, 104],
     'Date' : ['6/4/2023' ,'7/23/2023','4/28/2023','5/2/2023' ,'6/30/2023','7/11/2023','6/23/2023','7/12/2023','4/17/2023','5/12/2023','6/17/2023','7/22/2023'],
     'Flagged' : [0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1]})

# Convert dates
df['Date'] = pd.to_datetime(df.Date, format = '%m/%d/%Y')

# Find bad IDs (ones that had a flag before specific date)
bad_ids = df[(df.Flagged.eq(1)) & (df.Date < datetime.datetime(2023, 5, 1))].ID.unique()

# Find all values that are flagged and do not have a bad ID
df[(df.Flagged.eq(1)) & ~(df.ID.isin(bad_ids))]

输出:

    ID  Date        Flagged
6   103 2023-06-23  1
7   103 2023-07-12  1
9   104 2023-05-12  1
10  104 2023-06-17  1
11  104 2023-07-22  1