代码之家  ›  专栏  ›  技术社区  ›  user7852656

使用python 3.x进行一维插值

  •  0
  • user7852656  · 技术社区  · 6 年前

    我有一个数据,看起来像乙状结肠图,但相对于垂直线翻转。

    但绘图是绘制1d数据的结果,而不是某种函数。

    我的目标是在Y值为50%时找到X值。如您所见,当y正好在50%时,没有数据点。 我想到了国际刑警组织。但我不确定插值是否能在y值为50%时找到x值。所以我的问题是1)当y为50%时,你能用内插法找到x吗?或者2)是否需要将数据与某种函数相匹配?

    下面是我当前代码中的内容

    导入numpy as np 将matplotlib.pyplot导入为plt 我的x=[4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66] 我的_y_raw=np.数组([0.99470977497817203,0.99434995886145172,0.99470977497817203,0.9943434995886145172,0.98974611323163653,0.961630837657524,0.99327763333558441175,0.99333333952769251909,0.994282632925727534,0.98690514212121211611,0.991116677215533181,0.99149149418924828282880861,0.99133337777306268046464,0.99143143350633506335063800030303499,0.9915151580804680003494911454,0.99268261743308517,0.99289757252528282316,0.991002078611440663,0.99157171773324027,0.991125718248243558,0.990311608691035722,0.989781814266076905,0.989782674787969,0.98897835092187614,0.98517540405423909,0.9830894363666187076,0.96818181818181781994603,0.85563541881892147,0.615708181115487878787878781212316,0.999981818181818181818181818181818181818181818181818181818181818181818181818176040577个052,0.1465134838124245,0.07685314712214226,0.035831324928136087,0.021344669212790181]) my_y=my_y_raw/np.max(my_y_raw) plt.plot(我的x,我的y,color='k',markersize=40) 散点图(my_x,my_y,marker='*',label=“myplot”,color='k',edgecolor='k',lineidth=1,facecolors='none',s=50) Plt.Legend(loc=“左下”) plt.xlim([4102])

    但是,该图是绘制一维数据而不是某种函数的结果。

    我的目标是在Y值为50%时找到X值。如您所见,当y正好在50%时,没有数据点。 我想到了国际刑警组织。但我不确定插值是否能在y值为50%时找到x值。所以我的问题是1)当y为50%时,你能用内插法找到x吗?或者2)是否需要将数据与某种函数相匹配?

    下面是我当前代码中的内容

    import numpy as np
    import matplotlib.pyplot as plt
    
    
    my_x = [4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66]
    
    my_y_raw=np.array([0.99470977497817203, 0.99434995886145172, 0.98974611323163653, 0.961630837657524, 0.99327633558441175, 0.99338952769251909, 0.99428263292577534, 0.98690514212711611, 0.99111667721533181, 0.99149418924880861, 0.99133773062680464, 0.99143506380003499, 0.99151080464011454, 0.99268261743308517, 0.99289757252812316, 0.99100207861144063, 0.99157171773324027, 0.99112571824824358, 0.99031608691035722, 0.98978104266076905, 0.989782674787969, 0.98897835092187614, 0.98517540405423909, 0.98308943666187076, 0.96081810781994603, 0.85563541881892147, 0.61570811548079107, 0.33076276040577052, 0.14655134838124245, 0.076853147122142126, 0.035831324928136087, 0.021344669212790181])
    my_y=my_y_raw/np.max(my_y_raw)
    
    plt.plot(my_x, my_y,color='k', markersize=40)
    plt.scatter(my_x,my_y,marker='*',label="myplot", color='k', edgecolor='k', linewidth=1,facecolors='none',s=50)
    plt.legend(loc="lower left")
    plt.xlim([4,102])
    
    3 回复  |  直到 6 年前
        1
  •  2
  •   bfris    6 年前

    使用scipy

    最简单的插值方法是使用scipy interpolate.interp1d 函数。scipy与numpy密切相关,您可能已经安装了它。 interp1d 的优点是它可以为您对数据进行排序。这是以有点古怪的语法为代价的。在许多插值函数中,假设您试图从x值中插值y值。这些函数通常需要“x”值单调递增。在您的例子中,我们交换了x和y的正常意义。y值有一个异常值,正如@abhishek mishra指出的那样。对于您的数据,您是幸运的,您可以通过将离群值留在中而逃脱。

    导入numpy as np 将matplotlib.pyplot导入为plt 从scipy.interpolate导入interp1d 我的x=[4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46, 48、50、52、54、56、58、60、62、64、66条] my_y_raw=np.数组([0.99470977497817203,0.99434995886145172, 0.98974611323163653,0.961630837657524,0.9932763558441175, 0.9933892769251909,0.99428263292577534,0.9869051421271611, 0.99111667721533181,0.99149418924880861,0.99133773062680464, 0.99143506380003499,0.9915108464011454,0.99268261743308517, 0.9928975725282316,0.99100207861144063,0.99157171773324027, 0.99112571824824358,0.99031608691035722,0.9897810426076905, 0.989782674787969,0.98897835092187614,0.98517540405423909, 0.98308943666187076,0.9608181781994603,0.85563541881892147, 0.61570811548079107,0.3307627640577052,0.1465134838124245, 0.07685314712214226,0.035831324928136087,0.021344669212790181]) #设为“假定已排序”使scipy自动为您排序 F=interp1d(我的“原始”,我的“x”,假设“排序”=false) X新=F(0.5) print('插入值为',xnew) plt.绘图(my_x,my_y_raw,'x-',markersize=10) plt.plot(xnew,0.5,'x',color='r',markersize=20) plt.plot((0,xnew),(0.5,0.5),':') Plt.网格(真) 请显示())

    
    

    哪个给了

    插值值为56.81214249272691
    

    使用numpy

    numpy也有一个interp函数,但它不为您排序。如果你不分类,你会很抱歉的:

    不检查X坐标序列xp是否正在增加。如果是xp 不增加,结果是无意义的。

    我能让np.interp工作的唯一方法是将数据推送到结构化数组中。

    导入numpy as np 将matplotlib.pyplot导入为plt my_x=np.数组([4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46, 48,50,52,54,56,58,60,62,64,66],dtype=np.float) my_y_raw=np.数组([0.99470977497817203,0.99434995886145172, 0.98974611323163653,0.961630837657524,0.9932763558441175, 0.9933892769251909,0.99428263292577534,0.9869051421271611, 0.99111667721533181,0.99149418924880861,0.99133773062680464, 0.99143506380003499,0.9915108464011454,0.99268261743308517, 0.9928975725282316,0.99100207861144063,0.99157171773324027, 0.99112571824824358,0.99031608691035722,0.9897810426076905, 0.989782674787969,0.98897835092187614,0.98517540405423909, 0.98308943666187076,0.9608181781994603,0.85563541881892147, 0.61570811548079107,0.3307627640577052,0.1465134838124245, 0.07685314712214226,0.035831324928136087,0.021344669212790181], d类型=NP.浮动) dt=np.dtype([('x',np.float),('y',np.float)] 数据=np.zeros((len(my_x)),dtype=dt) 数据['x']=我的x 数据['Y']=我的原始数据 data.sort(order='y')按y值对数据进行就地排序 print('numpy interp gives',np.interp(0.5,data['y'],data['x']))

    
    

    哪个给了

    numpy interp给出56.81214249272691
    
    功能。scipy与numpy密切相关,您可能已经安装了它。有利于interp1d它可以为您对数据进行排序。这是以有点古怪的语法为代价的。在许多插值函数中,假设您试图从x值中插值y值。这些函数通常需要“x”值单调递增。在您的例子中,我们交换了x和y的正常意义。y值有一个异常值,正如@abhishek mishra指出的那样。对于您的数据,您是幸运的,您可以摆脱离开离群值在。

    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.interpolate import interp1d
    
    my_x = [4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,
    48,50,52,54,56,58,60,62,64,66]
    
    my_y_raw=np.array([0.99470977497817203, 0.99434995886145172, 
    0.98974611323163653, 0.961630837657524, 0.99327633558441175, 
    0.99338952769251909, 0.99428263292577534, 0.98690514212711611, 
    0.99111667721533181, 0.99149418924880861, 0.99133773062680464, 
    0.99143506380003499, 0.99151080464011454, 0.99268261743308517, 
    0.99289757252812316, 0.99100207861144063, 0.99157171773324027, 
    0.99112571824824358, 0.99031608691035722, 0.98978104266076905, 
    0.989782674787969, 0.98897835092187614, 0.98517540405423909, 
    0.98308943666187076, 0.96081810781994603, 0.85563541881892147, 
    0.61570811548079107, 0.33076276040577052, 0.14655134838124245, 
    0.076853147122142126, 0.035831324928136087, 0.021344669212790181])
    
    # set assume_sorted to have scipy automatically sort for you
    f = interp1d(my_y_raw, my_x, assume_sorted = False)
    xnew = f(0.5)
    
    print('interpolated value is ', xnew)
    
    plt.plot(my_x, my_y_raw,'x-', markersize=10)
    plt.plot(xnew, 0.5, 'x', color = 'r', markersize=20)
    plt.plot((0, xnew), (0.5,0.5), ':')
    plt.grid(True)
    plt.show()
    

    哪个给了

    interpolated value is  56.81214249272691
    

    enter image description here

    使用numpy

    numpy也有一个interp功能,但它不适合您。如果你不分类,你会很抱歉:

    不检查X坐标序列xp是否正在增加。如果是xp 没有增加,结果是胡说。

    我能让np.interp工作的唯一方法是将数据推送到结构化数组中。

    import numpy as np
    import matplotlib.pyplot as plt
    
    my_x = np.array([4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,
    48,50,52,54,56,58,60,62,64,66], dtype = np.float)
    
    
    my_y_raw=np.array([0.99470977497817203, 0.99434995886145172, 
    0.98974611323163653, 0.961630837657524, 0.99327633558441175, 
    0.99338952769251909, 0.99428263292577534, 0.98690514212711611, 
    0.99111667721533181, 0.99149418924880861, 0.99133773062680464, 
    0.99143506380003499, 0.99151080464011454, 0.99268261743308517, 
    0.99289757252812316, 0.99100207861144063, 0.99157171773324027, 
    0.99112571824824358, 0.99031608691035722, 0.98978104266076905, 
    0.989782674787969, 0.98897835092187614, 0.98517540405423909, 
    0.98308943666187076, 0.96081810781994603, 0.85563541881892147, 
    0.61570811548079107, 0.33076276040577052, 0.14655134838124245, 
    0.076853147122142126, 0.035831324928136087, 0.021344669212790181], 
    dtype = np.float)
    
    dt = np.dtype([('x', np.float), ('y', np.float)])
    data = np.zeros( (len(my_x)), dtype = dt)
    data['x'] = my_x
    data['y'] = my_y_raw
    
    data.sort(order = 'y') # sort data in place by y values
    
    print('numpy interp gives ', np.interp(0.5, data['y'], data['x']))
    

    哪个给了

    numpy interp gives  56.81214249272691
    
        2
  •  1
  •   Abhishek Mishra    6 年前

    如你所说,你的数据看起来像一个翻转的乙状结肠。我们可以假设你的函数是严格的递减函数吗?如果是这样,我们可以尝试以下方法:

    1. 删除数据没有严格减少的所有点。例如,对于您的数据,该点将接近0。
    2. 使用二进制搜索查找Y=0.5应该放在的位置。
    3. 现在你知道两对(x,y),你想要的y=0.5应该在哪里。
    4. 如果(x,y)对非常接近,可以使用简单的线性插值。
    5. 否则,你可以看到在这些对附近,乙状结肠的近似值是多少。
        3
  •  1
  •   Gobryas    6 年前

    您可能不需要将任何函数适合您的数据。只需找到以下两个元素:

    1. 最大的X,Y<50%
    2. Y>50%的最小X

    然后使用插值法找到x*。下面是代码

    my_x = np.array([4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66])
    my_y=np.array([0.99470977497817203, 0.99434995886145172, 0.98974611323163653, 0.961630837657524, 0.99327633558441175, 0.99338952769251909, 0.99428263292577534, 0.98690514212711611, 0.99111667721533181, 0.99149418924880861, 0.99133773062680464, 0.99143506380003499, 0.99151080464011454, 0.99268261743308517, 0.99289757252812316, 0.99100207861144063, 0.99157171773324027, 0.99112571824824358, 0.99031608691035722, 0.98978104266076905, 0.989782674787969, 0.98897835092187614, 0.98517540405423909, 0.98308943666187076, 0.96081810781994603, 0.85563541881892147, 0.61570811548079107, 0.33076276040577052, 0.14655134838124245, 0.076853147122142126, 0.035831324928136087, 0.021344669212790181])
    
    tempInd1 = my_y<.5 # This will only work if the values are monotonic
    
    x1 = my_x[tempInd1][0]
    y1 = my_y[tempInd1][0]
    
    x2 = my_x[~tempInd1][-1]
    y2 = my_y[~tempInd1][-1]
    
    scipy.interp(0.5, [y1, y2], [x1, x2])