Python Pandas:如果在2023年1月1日有行,则删除过去的行(按用户分组)

w46czmvw  于 2023-10-14  发布在  Python
关注(0)|答案(3)|浏览(103)

我试图强制所有用户的日期最早从2023年1月1日开始,有3个用例:
1.如果已经有关于01/01/2023的数据,我想保留它并删除以前的行
1.如果在01/01/2023上没有数据,但存在较旧的行,则我希望将日期更新为01/01/2023
1.如果用户的第1行在2023年1月1日之后,则保留它。
我想我应该从groupby()开始,但我不知道该怎么做?

数据来源:

| 用户|日期|值|
| --|--|--|
| USER1| 2019 - 06 - 01| 1000 |
| USER1| 2023年1月1日| 1000 |
| USER1| 2019 - 02 - 21| 1200 |
| USER1| 2023年2月2日| 1300 |
| USER2| 2021年01月06日**| 1000 |
| USER2| 2019 - 02 - 21| 1200 |
| USER2| 2023年2月2日| 1250 |
| USER3| 2023年02月06日| 1250 |

df = pd.DataFrame({"USER" : ['USER1', 'USER1', 'USER1', 'USER1', 'USER2', 'USER2', 'USER2', 'USER3'],
        "Date" :['01/06/2022', '01/01/2023', '01/02/2023', '02/02/2023', '01/06/2021', '01/02/2023', '02/02/2023', '02/06/2023'],
        "Value" :['1000', '1000', '1200', '1300', '1000', '1200', '1250', '1250'],}
    )

目标数据:

| 用户|日期|值||
| --|--|--|--|
| USER1| 2023年1月1日| 1000 |删除前一行,因为2023年1月1日已经有一行|
| USER1| 2019 - 02 - 21| 1200 ||
| USER1| 2023年2月2日| 1300 ||
| USER2| 2023年1月1日| 1000 |前值“01/06/2021”被强制为2023年1月1日|
| USER2| 2019 - 02 - 21| 1200 ||
| USER2| 2023年2月2日| 1250 ||
| USER3| 2023年02月06日| 1250 |保持价值不变,它已经在2023年1月1日之后|

xiozqbni

xiozqbni1#

如果我理解正确的话,你可以用clip强制一个最小日期,然后drop_duplicates保留最新的一行:

# ensure datetime
df['Date'] = pd.to_datetime(df['Date'])

out = (df.assign(Date=df['Date'].clip(lower=pd.Timestamp('2023-01-01')))
         .drop_duplicates(subset=['USER', 'Date'], keep='last')
       )
  • 注意。我假设日期已经排序(每个用户)。*

输出量:

USER       Date Value
1  USER1 2023-01-01  1000
2  USER1 2023-01-02  1200
3  USER1 2023-02-02  1300
4  USER2 2023-01-01  1000
5  USER2 2023-01-02  1200
6  USER2 2023-02-02  1250
7  USER3 2023-02-06  1250

中间体:

USER       Date Value       clip  duplicated
0  USER1 2022-01-06  1000 2023-01-01        True
1  USER1 2023-01-01  1000 2023-01-01       False
2  USER1 2023-01-02  1200 2023-01-02       False
3  USER1 2023-02-02  1300 2023-02-02       False
4  USER2 2021-01-06  1000 2023-01-01       False
5  USER2 2023-01-02  1200 2023-01-02       False
6  USER2 2023-02-02  1250 2023-02-02       False
7  USER3 2023-02-06  1250 2023-02-06       False
eoigrqb6

eoigrqb62#

我认为这是解决您的问题的最简单和最分解的方法

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

filtered_df = (df[df['Date'] >= '2023-01-01']
               .sort_values('Date')
               .groupby('USER', as_index=False)
               .first())

filtered_df['Date'] = pd.to_datetime('2023-01-01')

result_df = pd.concat([filtered_df, df[df['Date'] >= '2023-01-01']])

result_df.drop_duplicates(subset=['USER', 'Date'], keep='first', inplace=True)

result_df.sort_values(['USER', 'Date'], inplace=True)

现在您可以打印结果

print(result_df)
eulz3vhy

eulz3vhy3#

您可以用途:

#convert to datetimes
df['Date'] = pd.to_datetime(df['Date'])

date = pd.to_datetime('01/01/2023')

#test if greater or equal next values
m1 = df['Date'].ge(date).groupby(df['USER']).cummax()
#test if at least one match
m2 = df['USER'].isin(df.loc[df['Date'].eq(date),'USER'])

#set date
df.loc[~m1 & ~m2, 'Date'] = date

#remove previous less values if exist date
out = df[m1 | ~m2]

相关问题