【问题标题】:nan in interp1d scipyinterp1d scipy中的nan
【发布时间】:2016-01-05 10:52:07
【问题描述】:

我在 python 中使用 interp1d 处理以下代码,似乎 interp1d 的输出乘以查询点将数组的起始值输出为NaN。为什么?

Freq_Vector = np.arange(0,22051,1)
Freq_ref = np.array([20,25,31.5,40,50,63,80,100,125,160,200,250,315,400,500,630,750,800,1000,1250,1500,1600,2000,2500,3000,3150,4000,5000,6000,6300,8000,9000,10000,11200,12500,14000,15000,16000,18000,20000])   
W_ref=-1*np.array([39.6,32,25.85,21.4,18.5,15.9,14.1,12.4,11,9.6,8.3,7.4,6.2,4.8,3.8,3.3,2.9,2.6,2.6,4.5,5.4,6.1,8.5,10.4,7.3,7,6.6,7,9.2,10.2,12.2,10.8,10.1,12.7,15,18.2,23.8,32.3,45.5,50])
if FreqVector[-1] > Freq_ref[-1]:
    Freq_ref[-1] = FreqVector[-1]
WdB = interpolate.interp1d(Freq_ref,W_ref,kind='cubic',axis=-1, copy=True, bounds_error=False, fill_value=np.nan)(FreqVector)

WdB 中的前 20 个值是:

00000 = {float64} nan
00001 = {float64} nan
00002 = {float64} nan
00003 = {float64} nan
00004 = {float64} nan
00005 = {float64} nan
00006 = {float64} nan
00007 = {float64} nan
00008 = {float64} nan
00009 = {float64} nan
00010 = {float64} nan
00011 = {float64} nan
00012 = {float64} nan
00013 = {float64} nan
00014 = {float64} nan
00015 = {float64} nan
00016 = {float64} nan
00017 = {float64} nan
00018 = {float64} nan
00019 = {float64} nan
00020 = {float64} -39.6
00021 = {float64} -37.826313148

以下与前 20 个值在 maltab 中的输出相同:

-58.0424562952059
-59.2576965087483
-60.1150845850336
-60.6367649499501
-60.8448820293863
-60.7615802492306
-60.4090040353715
-59.8092978136973
-58.9846060100965
-57.9570730504576
-56.7488433606689
-55.3820613666188
-53.8788714941959
-52.2614181692886
-50.5518458177851
-48.7722988655741
-46.9449217385440
-45.0918588625830
-43.2352546635798
-41.3972535674226
-39.6000000000000
-37.8656383872004    

我怎样才能避免这种情况,并像 matlab 对 interp1d 那样实际具有实际值?

【问题讨论】:

    标签: python matlab


    【解决方案1】:

    我不知道确切的原因,但在查看绘制的数据时,拟合确实有效。

    from scipy import interpolate
    import numpy as np
    from matplotlib import pyplot as plt
    
    Freq_Vector = np.arange(0,22051.0,1)
    Freq_ref = np.array([20,25,31.5,40,50,63,80,100,125,160,200,250,315,\
    400,500,630,750,800,1000,1250,1500,1600,2000,2500,3000,3150,\
    4000,5000,6000,6300,8000,9000,10000,11200,12500,14000,15000,\
    16000,18000,20000])
    W_ref=-1*np.array([39.6,32,25.85,21.4,18.5,15.9,14.1,12.4,11,\
    9.6,8.3,7.4,6.2,4.8,3.8,3.3,2.9,2.6,2.6,4.5,5.4,6.1,8.5,10.4,7.3,7,\
    6.6,7,9.2,10.2,12.2,10.8,10.1,12.7,15,18.2,23.8,32.3,45.5,50])
    if Freq_Vector[-1] > Freq_ref[-1]:
        Freq_ref[-1] = Freq_Vector[-1]
    WdB = interpolate.interp1d(Freq_ref.tolist(),W_ref.tolist(),\
    kind='cubic', bounds_error=False)(Freq_Vector)
    
    plt.plot(Freq_ref,W_ref,'..',color='black',label='Reference')
    plt.plot(Freq_ref,W_ref,'-.',color='blue',label='Interpolated')
    plt.legend()
    

    情节如下:

    插值实际上正在发生,但拟合效果不如预期。但是,如果您的意图是拟合数据,为什么不使用样条插值器呢?它仍然是立方的,但不太容易过载。

    interpolate.InterpolatedUnivariateSpline(Freq_ref.tolist(),W_ref.tolist())(Freq_Vector)
    

    而且数据和情节出来的非常顺利。

    WdB
    Out[34]: 
    array([-114.42984432, -108.43602531, -102.72381906, ...,  -50.00471866,
            -50.00236016,  -50.        ])
    

    【讨论】:

      【解决方案2】:

      interp1d"将数组的起始值输出为NaN。为什么?"

      因为您提供给它的样本点集 (Freq_ref) 的下限为 20,而 interp1d 将为样本集之外的点分配值,如果 bounds_error 是 @,则 fill_value 的值987654332@ (docs)。 并且由于您请求对从019 的频率值进行插值,因此该方法为它们分配了NaN。 这与 Matlab 的默认值不同,默认值是使用请求的插值方法 (docs) 进行推断。

      话虽如此,我会谨慎地将 Matlab(或任何程序的)默认外推值称为“真实值”,因为外推可能非常困难并且很容易产生异常行为。对于您引用的值,Matlab 的 'cubic'/'pchip' 外推会生成图形:

      外推表明y-值翻转。这可能是正确的,但在作为福音之前应该仔细考虑。


      话虽这么说,如果您想为interp1d 方法添加外推能力,see this answer(因为我是 Matlab 人,而不是 Python 人(还))。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-12-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-28
        • 2015-06-23
        • 2013-09-30
        • 1970-01-01
        相关资源
        最近更新 更多