scipy 仅使用numpy使用interp1d对时间序列插值

wqnecbli  于 2022-11-10  发布在  其他
关注(0)|答案(1)|浏览(239)

我想用numpy和matplotlib绘制一个时间序列,使用标记来标记精确的点,并使用插值。基本上是这样的(数据是虚拟的,但功能是相同的,注意时间点之间的距离可能会变化):

import numpy as np
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt

T = [
    np.datetime64('2020-01-01T00:00:00.000000000'),
    np.datetime64('2020-01-02T00:00:00.000000000'),
    np.datetime64('2020-01-03T00:00:00.000000000'),
    np.datetime64('2020-01-05T00:00:00.000000000'),
    np.datetime64('2020-01-06T00:00:00.000000000'),
    np.datetime64('2020-01-09T00:00:00.000000000'),
    np.datetime64('2020-01-13T00:00:00.000000000'),
]
Z = [543, 234, 435, 765, 564, 235, 345]

fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot()
ax.plot(T, Z, 'o-')

然而,这里所做的插值只是连接点。我想使用scipy的interp1d来包括样条插值和其他类型的插值。因此,我尝试用以下代码替换最后一行:

ax.plot(T,Z, 'o')
ax.plot(T,interp1d(T, Z)(T), '-')

我得到了以下错误:

UFuncTypeError: ufunc 'true_divide' cannot use operands with types dtype('float64') and dtype('<m8[ns]')

阅读this answer时,我看到在插值过程中,我应该将T除以np.timedelta64(1, 's'),如下所示:

ax.plot(T,Z, 'o')
ax.plot(T,interp1d(T/np.timedelta64(1, 's'))(T), '-')

然而,我得到了一个更奇怪错误:

ufunc 'true_divide' cannot use operands with types dtype('<M8[ns]') and dtype('<m8[s]')

我该怎么办?

g0czyy6m

g0czyy6m1#

T中任何元素的数据类型都是np.datetime64,而不是np.timedelta64
因此,通过创建一个数据类型为m的numpy数组,将T的所有元素的dtype转换为np.timedelta64

T = np.array(
    np.datetime64('2020-01-01T00:00:00.000000000'),
    np.datetime64('2020-01-02T00:00:00.000000000'),
    np.datetime64('2020-01-03T00:00:00.000000000'),
    np.datetime64('2020-01-05T00:00:00.000000000'),
    np.datetime64('2020-01-06T00:00:00.000000000'),
    np.datetime64('2020-01-09T00:00:00.000000000'),
    np.datetime64('2020-01-13T00:00:00.000000000'),
    dtype='m')

然后,正如the documentation所建议的,我们必须将可转换为float类值的xy传递给scipy.interpolate.interp1d,以获得插值函数。我们将使用answer中建议的方法来实现这一点:


# Get an interpolation function f

f = scipy.interpolation.interp1d(x=T/np.timedelta64(1, 's'), y=Z)

最后,我们可以使用如下插值函数进行绘图:

ax.plot(T, f(T/np.timedelta64(1, 's'), '-')

将所有内容结合起来,我们将得到以下输出:

可以重现图像的代码:

import numpy as np
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt

T = np.array([
    np.datetime64('2020-01-01T00:00:00.000000000'),
    np.datetime64('2020-01-02T00:00:00.000000000'),
    np.datetime64('2020-01-03T00:00:00.000000000'),
    np.datetime64('2020-01-05T00:00:00.000000000'),
    np.datetime64('2020-01-06T00:00:00.000000000'),
    np.datetime64('2020-01-09T00:00:00.000000000'),
    np.datetime64('2020-01-13T00:00:00.000000000'),
], dtype='m')

Z = [543, 234, 435, 765, 564, 235, 345]

fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot()
ax.plot(T, Z, 'o')

f = interp1d(x=T/np.timedelta64(1, 's'), y=Z)

ax.plot(T, f(T/np.timedelta64(1, 's')), '-')
plt.show()

相关问题