pd.Grouper() 应用于日期时间时,更改原始日期列

pd.Grouper() when applied on datetime, changes the original column of dates

我有一个来自我的巨大数据框的示例数据框,如下所示。

import pandas as pd
import numpy as np

NaN = np.nan
data = {
    'ID':['AAQRB','AAQRB','AAQRB', 
'AHXSJ','AHXSJ','AHXSJ','GABOY','GABOY','GABOY','GHZGS','GHZGS','GHZGS'],
    'Date':['10/18/2021  10:52:53 PM','10/18/2021  10:53:55 PM', '10/25/2021  5:55:43 PM',
           '10/22/2021  10:37:06 PM','10/22/2021  10:38:22 PM','10/22/2021  10:39:56 PM',
           '11/1/2021  1:27:15 AM','11/1/2021  1:28:45 AM','11/2/2021  8:53:39 PM',
           '10/29/2021  11:13:57 PM', '10/29/2021  11:17:47 PM', '10/29/2021  11:19:15 PM'], 
    'Race_x':[NaN,NaN,NaN,NaN,NaN,1,NaN,NaN,1, NaN,NaN,1],
    'Vaccine':['TRUE',NaN,NaN,'TRUE',NaN,NaN,'TRUE',NaN,NaN,'FALSE',NaN,NaN],
    'Study_activity': 
   [NaN,'continue',NaN,NaN,'continue',NaN,NaN,'continue',NaN,NaN,'continue',NaN],
    'Who_Contacted': 
   [NaN,NaN,'WeContacted',NaN,NaN,'WeContacted',NaN,NaN,NaN,NaN,NaN,'WeContacted']}

test_df = pd.DataFrame(data)

目标是获取每个 ID 的所有第一个值,并将参与者的几行过滤为包含所有信息的一行。最终数据框应如下图所示。

代码已尝试

我尝试使用Grouper()函数,代码如下。

test_df['Date'] = pd.to_datetime(test_df['Date'])

test_df1 = (test_df.groupby(['ID', pd.Grouper(key='Date', freq='D')])
   .agg("first")
   .reset_index())
 baseline_df = test_df1[~test_df1.duplicated(subset = ['ID'], keep='first')]

但问题是,如果我使用 freq='D',那么第二天输入的 Race_x 值就会丢失。输出如下图所示。

如果我使用 freq='M' 或 freq='Y',将捕获其他值,但是 Dates 列值会更改,我们会得到每个 ID 的月末日期如下图

最后的 'Date' 列应该是每个 ID 'date' 的第一个条目,并且不应更改。

非常感谢任何帮助。谢谢!

创建一个虚拟列以按月分组:

>>> test_df.assign(month=test_df['Date'].dt.strftime('%Y-%m')) \
           .groupby(['ID', 'month']).agg('first') \
           .droplevel(1).reset_index() \
           .assign(Date=lambda x: x['Date'].dt.date)

      ID        Date  Race_x Vaccine Study_activity Who_Contacted
0  AAQRB  2021-10-18     NaN    TRUE       continue   WeContacted
1  AHXSJ  2021-10-22     1.0    TRUE       continue   WeContacted
2  GABOY  2021-11-01     1.0    TRUE       continue          None
3  GHZGS  2021-10-29     1.0   FALSE       continue   WeContacted

看起来您只想 groupby ID 并首先聚合 Date,其他一切都与您有有效值时一样。

假设所有 Race_xVaccineStudy_activityWho_Contacted 始终是 ID 的单个非 NaN 值。聚合前可以先bfill

这会将非 NaN 值收集到参与者的第一个条目中。

test_df['Date'] = pd.to_datetime('Date').dt.date
test_df.update(test_df.groupby('ID').bfill()) 

然后,尝试聚合。

test_df.groupby('ID').first().reset_index()


>>>     ID        Date Race_x Vaccine Study_activity Who_Contacted
 0   AAQRB  2021-10-18    NaN    TRUE       continue WeContacted
 1   AHXSJ  2021-10-22    1.0    TRUE       continue WeContacted
 2   GABOY  2021-11-01    1.0    TRUE       continue       NaN
 3   GHZGS  2021-10-29    1.0   FALSE       continue WeContacted