pandas 基于日期的实际插值

2nc8po8w  于 2023-01-15  发布在  其他
关注(0)|答案(3)|浏览(129)

这个问题是发生在Resampling on a multi index评论中的后续问题。
我们从以下数据开始:

data=pd.DataFrame({'dates':['2004','2008','2012'],'values':[k*(1+4*365) for k in range(3)]})
data['dates']=pd.to_datetime(data['dates'])
data=data.set_index('dates')

这就是它所产生的:

现在,当我重新采样和插值

data.resample('A').mean().interpolate()

我获得以下信息:

但我想要的(问题已经是重采样,而不是插值步骤)是

2004-12-31     365
2005-12-31     730
2006-12-31    1095
2007-12-31    1460
2008-12-31    1826
2009-12-31    2191
2010-12-31    2556
2011-12-31    2921
2012-12-31    3287

所以我需要对给定的数据进行线性插值。
为了更清楚地说明这一点,我写了一个函数来完成这项工作。然而,我仍然在寻找一个内置的解决方案(我自己的函数是糟糕的编码,因为一个非常丑陋的运行时):

def fillResampleCorrectly(data,resample):
    for i in range(len(resample)):
        currentDate=resample.index[i]
        for j in range(len(data)):
            if currentDate>=data.index[j]:
                if j<len(data)-1:
                    continue
            valueBefore=data[data.columns[0]].iloc[j-1]
            valueAfter=data[data.columns[0]].iloc[j]
            dateBefore=data.index[j-1]
            dateAfter=data.index[j]
            currentValue=valueBefore+(valueAfter-valueBefore)*((currentDate-dateBefore)/(dateAfter-dateBefore))
            resample[data.columns[0]].iloc[i]=currentValue
            break
uxhixvfz

uxhixvfz1#

我找不到一个直接的方法来获得你的精确输出。问题是第一年01-01和31-12之间的重新采样。
但是,您可以使用以下命令模拟结果:

out = data.resample('A', label='right').mean().interpolate(method='time') + 365

或者:

s = data.resample('A', label='right').mean().interpolate(method='time')

out = s + (s.index[0] - data.index[0]).days

输出:

values
dates             
2004-12-31   365.0
2005-12-31   730.0
2006-12-31  1095.0
2007-12-31  1460.0
2008-12-31  1826.0
2009-12-31  2191.0
2010-12-31  2556.0
2011-12-31  2921.0
2012-12-31  3287.0
g0czyy6m

g0czyy6m2#

什么是"实际"插值?您正在考虑闰年,这使得这是一个非线性关系。
生成一个从年底开始的df(并将2004年记为闰年):

data = pd.DataFrame({'dates': ['2004-12-31', '2008-12-31', '2012-12-31'], 'values': [
                    366 + k * (1 + 4 * 365)  for k in range(3)]})
data['dates'] = pd.to_datetime(data['dates'])
data = data.set_index('dates')
values
dates   
2004-12-31  366
2008-12-31  1827
2012-12-31  3288

如前所述进行重采样和插值(data = data.resample('A').mean().interpolate())。顺便说一下,重采样中的A是年底,AS是年初。如果我们查看每一步之间的差异(data - data.shift(1)),我们得到:

values
dates   
2004-12-31  NaN
2005-12-31  365.25
2006-12-31  365.25
2007-12-31  365.25
2008-12-31  365.25
2009-12-31  365.25
2010-12-31  365.25
2011-12-31  365.25
2012-12-31  365.25

如我们从线性插值所期望的,可以通过将np.floor应用于结果来实现期望的结果:
一个三个三个一个
差值data - data.shift(1)

values
dates   
2004-12-31  NaN
2005-12-31  365.0
2006-12-31  365.0
2007-12-31  365.0
2008-12-31  366.0
2009-12-31  365.0
2010-12-31  365.0
2011-12-31  365.0
2012-12-31  366.0

由闰年引起的非线性关系。

sc4hvdpw

sc4hvdpw3#

我刚想到一个主意而且很管用:

dailyData=data.asfreq('D').interpolate()
dailyData.groupby(dailyData.index.year).tail(1)

只有去年选择了错误的日期,但这对我来说完全没问题。重要的是日期与值匹配。

相关问题