很抱歉出现这个令人困惑的问题,我不知道用什么最好的方法将其总结成一个更具描述性的问题。
我有一个数据帧,它有两个日期时间列,一个只给出日期,另一个向日期列添加特定的小时和分钟值,比如"date_hour_minute"。Date_Hour_Minute列有很多缺失值,但Date列没有。
Row | Date | ID | Date_Hour_Minute
==========================================
1 | 02/21 | 25 | 02/21 06:02
2 | 02/21 | 30 | NA
3 | 02/21 | 30 | NA
4 | 02/21 | 25 | NA
5 | 02/21 | 25 | 02/21 07:10
6 | 02/21 | 30 | NA
7 | 02/22 | 30 | NA
现在,我想将Date_Hour_Minute列中的所有NA值替换为相应的Date值,并在其后面添加小时/分钟值。使用fillna
,我可以很容易地在Date后面添加午夜时间,并将NA替换为
df.Date_Hour_Minute = df.Date_Hour_Minute.fillna(df.Date)
导致
Row | Date | ID | Date_Hour_Minute
============================================
1 | 02/21 | 25 | 02/21 06:02
2 | 02/21 | 30 | 02/21 00:00
3 | 02/21 | 30 | 02/21 00:00
4 | 02/21 | 25 | 02/21 00:00
5 | 02/21 | 25 | 02/21 07:10
6 | 02/21 | 30 | 02/21 00:00
7 | 02/22 | 30 | NA
但是,这会在Date_Hour_Minute列中创建大量重复项。是否有一种方法可以使每次替换都是唯一的,即在第二次遇到NA值时加1分钟,然后在下一个NA值上加2分钟,依此类推,以特定ID和日期?(如果看到该ID的新日期,则计数器重置(。所以结果看起来像这样-
Row | Date | ID | Date_Hour_Minute
============================================
1 | 02/21 | 25 | 02/21 06:02
2 | 02/21 | 30 | 02/21 00:00
3 | 02/21 | 30 | 02/21 00:01 (add 1 minute to previous NA value with same date for ID=30)
4 | 02/21 | 25 | 02/21 00:00
5 | 02/21 | 25 | 02/21 07:10
6 | 02/21 | 30 | 02/21 00:02
7 | 02/22 | 30 | 02/22 00:00 (reset increment counter because new date for ID=30)
这种方法使用字典来保存下一个默认的时间值,由id和日期键控
import pandas as pd
from io import StringIO
from datetime import timedelta
# Test data
df1 = pd.read_csv(StringIO ("""
Row|Date|ID|Date_Hour_Minute
1|2018-02-21|25|2018-02-21 06:02
2|2018-02-21|30|NA
3|2018-02-21|30|NA
4|2018-02-21|25|NA
5|2018-02-21|25|2018-02-21 07:10
6|2018-02-21|30|NA
7|2018-02-22|30|NA
"""), sep= "|", parse_dates= ["Date", "Date_Hour_Minute"], infer_datetime_format = True)
# Global dictionary to cache the last assigned value by group
last_date = {}
def enhance_date(p):
"""
Expects a triple of Date, Id, Date_Hour_Minute
Returns the modified Date_Hour_Minute
"""
# Define the cache
global last_date
#Extract the parameters
date = p[0]
id = p[1]
date_hour_minute = p[2]
# Make a key for the dictionary cache with id and date
key = str(id) + "|" + str(date)
# Apply the rules ans save next value in cache
if pd.isnull(date_hour_minute):
if key in last_date:
r = last_date[key]
last_date[key] = r + timedelta(minutes=1)
else:
r = date
last_date[key] = r + timedelta(minutes=1)
else:
r = date_hour_minute
return r
# Apply to each triple and assign to a new column
df1["New_Date_Hour_Minute"] = df1[["Date", "ID", "Date_Hour_Minute"]].apply(enhance_date, axis=1)
print(df1)
结果
Row Date ID Date_Hour_Minute New_Date_Hour_Minute
0 1 2018-02-21 25 2018-02-21 06:02:00 2018-02-21 06:02:00
1 2 2018-02-21 30 NaT 2018-02-21 00:00:00
2 3 2018-02-21 30 NaT 2018-02-21 00:01:00
3 4 2018-02-21 25 NaT 2018-02-21 00:00:00
4 5 2018-02-21 25 2018-02-21 07:10:00 2018-02-21 07:10:00
5 6 2018-02-21 30 NaT 2018-02-21 00:02:00
6 7 2018-02-22 30 NaT 2018-02-22 00:00:00