首页 文章

按'ffill'和'interpolate'填充NaN,具体取决于Python中NaN发生日期的时间

提问于
浏览
1

我想使用'mean'和'interpolate'在df中填充NaN,具体取决于NaN发生的当天 . 如下所示,第一个NaN发生在早上6点,第二个NaN发生在上午8点 .

02/03/2016 05:00    8
02/03/2016 06:00    NaN
02/03/2016 07:00    1
02/03/2016 08:00    NaN
02/03/2016 09:00    3

我的df包含数千天 . 我希望在早上7点之前对任何NaN应用'ffill',并对早上7点之后发生的那些应用'interpolate' . 我的数据是从早上6点到下午6点 .

我的尝试是:

df_imputed = (df.between_time("00:00:00", "07:00:00", include_start=True, include_end=False)).ffill()
df_imputed = (df.between_time("07:00:00", "18:00:00", include_start=True, include_end=True)).interpolate()

但它将我的df降低到指定的时间段,而不是按我的意愿填充NaN .

编辑:我的df包含大约400列,因此该过程将适用于所有列 .

1 回答

  • 4

    原始问题:单一系列的 Value 观

    您可以根据条件定义布尔系列,然后根据numpy.where适当地定义interpolateffill

    # setup
    df = pd.DataFrame({'date': ['02/03/2016 05:00', '02/03/2016 06:00', '02/03/2016 07:00',
                                '02/03/2016 08:00', '02/03/2016 09:00'],
                       'value': [8, np.nan, 1, np.nan, 3]})
    df['date'] = pd.to_datetime(df['date'])
    
    # construct Boolean switch series
    switch = (df['date'] - df['date'].dt.normalize()) > pd.to_timedelta('07:00:00')
    
    # use numpy.where to differentiate between two scenarios
    df['value'] = np.where(switch, df['value'].interpolate(), df['value'].ffill())
    
    print(df)
    
                     date  value
    0 2016-02-03 05:00:00    8.0
    1 2016-02-03 06:00:00    8.0
    2 2016-02-03 07:00:00    1.0
    3 2016-02-03 08:00:00    2.0
    4 2016-02-03 09:00:00    3.0
    

    更新的问题:多个值系列

    使用多个值列,您可以使用pd.DataFrame.whereiloc调整上述解决方案 . 或者,您可以使用loc或其他方式(例如filter)来选择列,而不是 iloc

    # setup
    df = pd.DataFrame({'date': ['02/03/2016 05:00', '02/03/2016 06:00', '02/03/2016 07:00',
                                '02/03/2016 08:00', '02/03/2016 09:00'],
                       'value': [8, np.nan, 1, np.nan, 3],
                       'value2': [3, np.nan, 2, np.nan, 6]})
    df['date'] = pd.to_datetime(df['date'])
    
    # construct Boolean switch series
    switch = (df['date'] - df['date'].dt.normalize()) > pd.to_timedelta('07:00:00')
    
    # use numpy.where to differentiate between two scenarios
    df.iloc[:, 1:] = df.iloc[:, 1:].interpolate().where(switch, df.iloc[:, 1:].ffill())
    
    print(df)
    
                     date  value  value2
    0 2016-02-03 05:00:00    8.0     3.0
    1 2016-02-03 06:00:00    8.0     3.0
    2 2016-02-03 07:00:00    1.0     2.0
    3 2016-02-03 08:00:00    2.0     4.0
    4 2016-02-03 09:00:00    3.0     6.0
    

相关问题