1

例如,我有一组日期和一组以不同间隔拍摄的日期。

只是为了说明起见,假设数字是从今天(9 月 29 日)到现在(12 月 29 日)三个月后的每天,从三个月后到两年后的每月一次,从两年到 10 年的每季度一次,再过 50 年之后的每年一次年。

现在的要求是,我们仍然遵循所有日期间隔“模式”,但时间序列应该从每个季度末开始(所以 3 月 31 日、6 月 30 日、9 月 30 日和 12 月 31 日),数字线性插值在-之间。因此,使用上面的示例,我的新系列应该是从 9 月 30 日(第一季度末)到 12 月 31 日的每日数字,从 2012 年 12 月 31 日到 2014 年 12 月 31 日的每月数字,从 2014 年 12 月 31 日到 2022 年 12 月 31 日的每季度以及之后的每年,新时间序列中所有不在旧时间序列中的价格都是使用线性插值计算的)。

有什么方法可以有效地做到这一点,有没有我可以使用的代码示例?

感谢您的帮助!

4

1 回答 1

1

这是一种仅使用datetimeand的方法calendar。不过篇幅较长,请注意。

首先,我们需要一种方法来制作所需的时间序列

月份和季度有点棘手,例如,哪个日期是 1 月 31 日之后的一个月?但方法可能如下所示:

为了测试,我包括生成属于日期的随机值。

from datetime import datetime, timedelta, date
import calendar
from random import random

def makeseries(startdate):
    datesA = [startdate] # collect the dates in this list
    valsA = [random()]   # and the randomly generated 'data' in this one
    date = startdate    

    # add days
    step = timedelta(1)
    while date - startdate <= timedelta(91):
        date += step
        datesA += [date]
        valsA += [random()]

    # add months
    step = timedelta(30)
    while date - startdate <= timedelta(2*365):
        if date.month in [1,3,5,7,8,10,12]:
            date += timedelta(1)
        elif date.month == 2:
            date -= timedelta(2)
        date += step
        datesA += [date]
        valsA += [random()]

    # add quarters
    step = timedelta(91)
    while date - startdate <= timedelta(int(365*10)):
        date += step
        if date.year % 4 == 0:
            date += timedelta(1)
        datesA += [date]
        valsA += [random()]

    # add years
    step = timedelta(365)
    while date - startdate <= timedelta(int(365*50)):
        date += step
        if date.year % 4 == 0:
            date += timedelta(1)
        datesA += [date]
        valsA += [random()]

    return datesA, valsA

然后,一个简单的方法在一系列日期中找到与给定日期最近的日期

def findIndexOfNearest(series, D):
    # returns the index of the date in series that is closest to, but greater than D
    for i, date in enumerate(series):
        if date > D:
            return i
    return None

生成两个时间序列,加上第一个序列的一些模拟日期

thisyear = datetime.today().year
quarterEndMonth = (datetime.today().month+2)//3*3
quarterEndDay = calendar.monthrange(thisyear, quarterEndMonth)[1]

d1,v1 = makeseries(date.today())
d2,_ = makeseries(date(thisyear,quarterEndMonth, quarterEndDay))
v2 = []

使用 timedeltas进行插值并打印插值

for d in d2: 
    i = findIndexOfNearest(d1, d)
    if i:
        prev = d1[i-1]
        next = d1[i]
        prevRatio = 1-(d-prev).total_seconds()/(next-prev).total_seconds()
        nextRatio = 1-(next-d).total_seconds()/(next-prev).total_seconds()
        interp = prevRatio*v1[i-1] + nextRatio*v1[i]
        v2 += [interp]
        print("%s = %.2f * %s + %.2f * %s" % (d, prevRatio, prev, nextRatio, next))
        print("%17.2f * %10.2f + %.2f * %10.2f = %.2f" % \
               (prevRatio, v1[i-1], nextRatio, v1[i], interp))
    else: # date to be interpolated is past last original date
        v2 += [v1[-1]]
        print("%s = 1.00 * %s = %24.2f" % (d,d1[-1],v1[-1]))

一些示例输出:

在这里,原始系列刚刚切换到 3 个月的间隔,一个日期在 11 月,另一个日期在明年 2 月。我们插值的日期是 12 月。

                     original           original
                      date                date
                        v                   v
2014-12-02 = 0.69 * 2014-11-04 + 0.31 * 2015-02-03
     ^       0.69 *       0.95 + 0.31 *       0.10 = 0.69
     |         ^           ^       ^           ^       ^
     |         |        original   |       original   interpolated 
date from      |         value     |         value       value
2nd series   weight              weight
于 2012-10-04T00:27:58.380 回答