DataFrame按日期字段填充NaN值, 填充成前一天的所有数据

本文介绍了一种在处理金融数据时,如何解决非交易日数据缺失的问题,通过使用Pandas库,实现对缺失数据的向前填充,确保数据的连续性和准确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

工作中遇到的, 有些数据只有在交易日才有值,在非交易日会显示NaN,需要填充成前一个交易日的数据
如果每天只有一条,可以用ffill
但每天有多条, 直接用ffill是不行的
假设现有df是这样的,需要根据NaN的日期找到上一个有数据的日期, 填充一模一样的数据
在这里插入图片描述
期望输出的df如下,这里2018-01-02和2018-02-03都填充2018-01-01的数据
在这里插入图片描述
=====2020.12.31更新, 重写了个更简洁的算法代码
方法2代码如下

import pandas as pd
import numpy as np

df=pd.DataFrame(np.arange(20).reshape(5,4),columns=list('ABCD'))
df['symbol'] = ['0001.SH', '0002.SH', '0003.SH', '0004.SH', '0005.SH']
df.loc[2:3,:]=np.nan
df['the_date'] = ['2018-01-01', '2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04']
print(df)#打印结果如下
"""
      A     B     C     D   symbol    the_date
0   0.0   1.0   2.0   3.0  0001.SH  2018-01-01
1   4.0   5.0   6.0   7.0  0002.SH  2018-01-01
2   NaN   NaN   NaN   NaN      NaN  2018-01-02
3   NaN   NaN   NaN   NaN      NaN  2018-01-03
4  16.0  17.0  18.0  19.0  0005.SH  2018-01-04
"""
#将NaN值填充为known,否则不方便后面的处理
df.fillna('unknown',inplace=True)
#按已经连续的日期列,进行groupby
df_grouped = df.groupby(by=['the_date'])
#pre_df和new_df用于填充
pre_df  = pd.DataFrame()
new_df = pd.DataFrame()
#循环遍历按日期分组后的dataframe
for i in df_grouped:
    #取出单天的dataframe
    df_day = i[1]
    #设置日期为index,方便后面取出其他列的值并判断其他列的值是不是unknown
    df_day.set_index('the_date',inplace=True)
    #判断如果单天dataframe的值都为unknown
    if (df_day.values=='unknown').all():
        #取出上一天的dataframe,并把日期设置为今天,即该天填充了上一日数据形成了一个新的dataframe
        pre_df.loc[:,'the_date']=df_day.index.values[0]
        #将上一步结果赋值, 待后面添加到new_df
        df_fill = pre_df
    else:#否则,将今日的单天dataframe赋值,待后面添加到new_df
        df_fill=df_day.reset_index()
    #将每次循环的结果添加给new_df
    new_df = new_df.append(df_fill)
    #pre_df更新为每次的填充dataframe,以便下次使用
    pre_df = df_fill

print(new_df)#打印结果如下,数据填充完成
"""
     the_date     A     B     C     D   symbol
0  2018-01-01   0.0   1.0   2.0   3.0  0001.SH
1  2018-01-01   4.0   5.0   6.0   7.0  0002.SH
0  2018-01-02   0.0   1.0   2.0   3.0  0001.SH
1  2018-01-02   4.0   5.0   6.0   7.0  0002.SH
0  2018-01-03   0.0   1.0   2.0   3.0  0001.SH
1  2018-01-03   4.0   5.0   6.0   7.0  0002.SH
0  2018-01-04  16.0  17.0  18.0  19.0  0005.SH
"""

=======以下是最初的写法,比较繁琐
方法1代码如下:

import pandas as pd
import numpy as np


def fill_nan(df,col,fill_col):

    valid_index = df[col].first_valid_index()

    df = df.iloc[valid_index:, :]
    df[col] = df[col].fillna('unknown')
    df.set_index([fill_col],inplace=True)
    nan_index = df[df[col]=='unknown'].index.tolist()
    df2 = df.reset_index()
    for i in nan_index:
        pre_index = df2[df2[fill_col]==i].index.tolist()[0]-1
        pre_day = df2.loc[pre_index,fill_col]
        fill_frame = df2[df2[fill_col]==pre_day]
        fill_frame[fill_col]=i
        df2 = df2.append(fill_frame)
        df2=df2[~((df2[fill_col]==i)&(df2[col]=='unknown'))]
        df2 = df2.sort_values(fill_col).reset_index(drop=True)
    return df2

if __name__=='__main__':
    df=pd.DataFrame(np.arange(20).reshape(5,4),columns=list('ABCD'))
    df['symbol'] = ['0001.SH', '0002.SH', '0003.SH', '0004.SH', '0005.SH']
    df.loc[2:3,:]=np.nan
    df['the_date'] = ['2018-01-01', '2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04']
    print(df)

    df = fill_nan(df,'symbol',"the_date")
    print(df)

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值