【问题标题】:Filling NaN by 'ffill' and 'interpolate' depending on time of the day of NaN occurrence in Python根据 Python 中 NaN 发生的时间,通过“填充”和“插值”填充 NaN
【发布时间】:2019-05-10 20:41:48
【问题描述】:

我想根据 NaN 发生在一天中的什么时间使用“均值”和“插值”将 NaN 填充到 df 中。如下所示,第一个 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 应用“填充”,并为早上 7 点之后发生的那些应用“插值”。我的数据是从早上 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 列,因此该过程将适用于所有列。

【问题讨论】:

    标签: python pandas datetime dataframe series


    【解决方案1】:

    原问题:单系列值

    您可以根据您的条件定义一个布尔系列,然后通过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 调整上述解决方案。或者,代替iloc,您可以使用loc 或其他方式(例如filter)选择列:

    # 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
    

    【讨论】:

    • 感谢您的有用提示。我可以将它用于一列df。但是,我忘了写我的 df 有很多列。请查看我的编辑。
    • 如果列'日期'被设置为索引怎么办?
    • 使用df.index 或通过df.reset_index() 提升到列。
    • 对不起,但首先它拒绝'dt',然后它给出ValueError: Array conditional must be same shape as self
    • 无法复制,对我来说很好用。看起来您无法将数据框操作为我定义的格式。这很可能是another question
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-05
    • 2021-01-24
    • 1970-01-01
    • 2015-02-14
    • 2015-10-05
    相关资源
    最近更新 更多