【问题标题】:How to avoid long integer during date extraction using pandas?如何在使用 pandas 提取日期期间避免长整数?
【发布时间】:2021-09-22 09:33:33
【问题描述】:

我有一个如下所示的数据框。这是post的延续@

df = pd.DataFrame({'person_id': [101,101,101,101,202,202,202],
                   'person_type':['A','A','B','C','D','B','A'],
                   'login_date':['5/7/2013 09:27:00 AM','09/08/2013 11:21:00 AM','06/06/2014 08:00:00 AM','06/06/2014 05:00:00 AM','12/11/2011 10:00:00 AM','13/10/2012 12:00:00 AM','13/12/2012 11:45:00 AM'],
                   'logout_date':[np.nan,'11/08/2013 11:21:00 AM',np.nan,'06/06/2014 05:00:00 AM',np.nan,'13/10/2012 12:00:00 AM',np.nan]})
df.login_date = pd.to_datetime(df.login_date)
df.logout_date = pd.to_datetime(df.logout_date)

我想对 logout_date 列应用 2 条规则

规则 1 - 如果人员类型为 B、C、D、E 且 logout_date 为 NaN,则复制登录日期值

规则 2 - 如果人员类型为 A 且 logout_date 为 NaN,则将登录日期添加 2 天

当我尝试以下方法时

m1 = df['person_type'].isin(['B','C','D'])
m2 = df['person_type'].isin(['A'])
m3 = df['logout_datetime'].isna()

df['logout_datetime'] = np.select([m1 & m3, m2 & m3],
                              [df['login_datetime'], df['login_datetime'] + pd.DateOffset(days=2)],
                               default=df['logout_datetime'])
df['logout_date'] = np.select([m1 & m3, m2 & m3],
                              [df['login_datetime'].dt.date, (df['login_datetime'] + pd.DateOffset(days=2)).dt.date],
                               default=df['logout_datetime'])

我想使用np.select 直接获取logout_date 列,如示例代码所示。

目前我得到的输出如下所示是不正确的

我不明白为什么有些行会导致问题,而其他行工作正常。

可以帮我解决这个问题吗?我希望我的输出具有正确的日期值

【问题讨论】:

  • 可以,注销数据可以有na

标签: python pandas dataframe datetime pandas-groupby


【解决方案1】:

我认为问题是缺少转换 np.select (default=df['logout_datetime']) 中的 default 参数并将其更改为 default=df['logout_datetime'].dt.date 对于从 np.select 返回的相同类型:

df['logout_date'] = np.select([m1 & m3, m2 & m3],
                              [df['login_date'].dt.date, 
                              (df['login_date'] + pd.DateOffset(days=2)).dt.date],
                               default=df['logout_date'].dt.date)
print (df)
   person_id person_type          login_date logout_date
0        101           A 2013-05-07 09:27:00  2013-05-09
1        101           A 2013-09-08 11:21:00  2013-11-08
2        101           B 2014-06-06 08:00:00  2014-06-06
3        101           C 2014-06-06 05:00:00  2014-06-06
4        202           D 2011-12-11 10:00:00  2011-12-11
5        202           B 2012-10-13 00:00:00  2012-10-13
6        202           A 2012-12-13 11:45:00  2012-12-15

如果需要default 和日期时间然后Series.dt.normalize 删除时间(设置为00:00:00)并且所有类型都是datetimes,所以工作得很好:

df['logout_date'] = np.select([m1 & m3, m2 & m3],
                              [df['login_date'].dt.normalize(), 
                               (df['login_date'] + pd.DateOffset(days=2)).dt.normalize()],
                               default=df['logout_date'])
print (df)
   person_id person_type          login_date         logout_date
0        101           A 2013-05-07 09:27:00 2013-05-09 00:00:00
1        101           A 2013-09-08 11:21:00 2013-11-08 11:21:00
2        101           B 2014-06-06 08:00:00 2014-06-06 00:00:00
3        101           C 2014-06-06 05:00:00 2014-06-06 05:00:00
4        202           D 2011-12-11 10:00:00 2011-12-11 00:00:00
5        202           B 2012-10-13 00:00:00 2012-10-13 00:00:00
6        202           A 2012-12-13 11:45:00 2012-12-15 00:00:00

对于原始日期时间使用:

df['logout_date'] = np.select([m1 & m3, m2 & m3],
                              [df['login_date'], 
                               (df['login_date'] + pd.DateOffset(days=2))],
                               default=df['logout_date'])
print (df)
   person_id person_type          login_date         logout_date
0        101           A 2013-05-07 09:27:00 2013-05-09 09:27:00
1        101           A 2013-09-08 11:21:00 2013-11-08 11:21:00
2        101           B 2014-06-06 08:00:00 2014-06-06 08:00:00
3        101           C 2014-06-06 05:00:00 2014-06-06 05:00:00
4        202           D 2011-12-11 10:00:00 2011-12-11 10:00:00
5        202           B 2012-10-13 00:00:00 2012-10-13 00:00:00
6        202           A 2012-12-13 11:45:00 2012-12-15 11:45:00

【讨论】:

  • 即使我不使用dt.date 作为默认值,它也应该只填充日期时间值对吗?为什么它用一个整数填充?..upvited
  • @TheGreat - 因为与dates 和datetimes 不匹配
  • @TheGreat - df['login_date'].dt.date 返回日期,然后 (df['login_date'] + pd.DateOffset(days=2)).dt.date 返回 dates 和 default=df['logout_date'] 返回日期时间
  • 对于df['logout_datetime']的默认值,不保留实际值2014-06-06 08:00:00,而是改为2014-06-06 00:00:00
  • @TheGreat - 需要像第二段答案这样的输出吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-30
  • 2021-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-14
  • 1970-01-01
相关资源
最近更新 更多