熊猫:填充另一列中缺少的日期时间值,但如果重复则增加每次替换的次数

时间:2018-12-02 22:51:16

标签: python pandas

很抱歉这个令人困惑的问题,我不知道将其总结成更具描述性的问题的最佳方法。

我有一个数据框,其中有两个datetime列,一个仅给出日期,而另一个给date列添加特定的小时和分钟值,例如“ 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,我可以轻松地将午夜时间附加到日期上,并用它替换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分钟,然后再添加2分钟到下一个NA值,等等以特定的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)       

1 个答案:

答案 0 :(得分:0)

这种方法使用字典来保存下一个默认的ime值,该值由id和date键

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