如何按长度重采样数组-python

我有一个数组,我想将其重采样到指定长度
array = [0.01,0.04,0.04....1] # len10
期望结果
[0.11,0.44,1] # len 3
[1e-4,2e-4,....1] # len 100
# 例子用的是 f(x)=x^2
实际问题 用plot作图

img


这个数组的长度为8k
我想在不改变其大致形状的前提下将其重采样到1.5w

我的解答思路和尝试过的方法

这不是整数间距的缩放,所以用普通的resample方法好像难以解决该问题【改采样率】

我尝试重待采样数组,再线性的化为与目标长度相同的数组

def _lineResample(x1, y1, x2, y2, x):
    '''
    :param x1:pointA x
    :param y1: pointA y
    :param x2: pointB x
    :param y2: pointB y
    :param x: x in llineAB
    :return: y in lineAB
    '''
    return (y2 - y1)*(x - x1) / (x2 - x1) + y1


def resampleBylen(orig_numpy, target_numpy_len: int):
    # 将orig重采样为和target一样长度的
    orig_numpy_len = len(orig_numpy)
    if orig_numpy_len == target_numpy_len:
        return orig_numpy
    scale = target_numpy_len/orig_numpy_len

    big_orig_numpy ,sr = resample(orig_numpy,8000,8000*(int(scale)+1))
    big_orig_numpy = big_orig_numpy.tolist()
    big_orig_numpy_len = len(big_orig_numpy)
    result = []
    for i in range(target_numpy_len):
        absPostion = i*big_orig_numpy_len/target_numpy_len
        left = int(absPostion)
        right = left+1
        y = _lineResample(left,big_orig_numpy[left],right,big_orig_numpy[right],absPostion)
        result.append(y)

但是不但效果不好,而且消耗时间惊人的长

不知道如何解决这个问题


from matplotlib import pyplot
import numpy
from interval import Interval, IntervalSet

def overlap(rect1, rect2):
  """Calculate the overlap between two rectangles"""
  xInterval = Interval(rect1[0][0], rect1[1][0]) & Interval(rect2[0][0], rect2[1][0])
  yInterval = Interval(rect1[0][1], rect1[1][1]) & Interval(rect2[0][1], rect2[1][1])
  area = (xInterval.upper_bound - xInterval.lower_bound) * (yInterval.upper_bound - yInterval.lower_bound)
  return area


def meanInterp(data, m, n):

  newData = numpy.zeros((m,n))
  mOrig, nOrig = data.shape

  hBoundariesOrig, vBoundariesOrig = numpy.linspace(0,1,mOrig+1), numpy.linspace(0,1,nOrig+1)
  hBoundaries, vBoundaries = numpy.linspace(0,1,m+1), numpy.linspace(0,1,n+1)

  for iOrig in range(mOrig):
    for jOrig in range(nOrig):
      for i in range(m):
        if hBoundaries[i+1] <= hBoundariesOrig[iOrig]: continue
        if hBoundaries[i] >= hBoundariesOrig[iOrig+1]: break
        for j in range(n):
          if vBoundaries[j+1] <= vBoundariesOrig[jOrig]: continue
          if vBoundaries[j] >= vBoundariesOrig[jOrig+1]: break

          boxCoords = ((hBoundaries[i], vBoundaries[j]),(hBoundaries[i+1], vBoundaries[j+1]))
          origBoxCoords = ((hBoundariesOrig[iOrig], vBoundariesOrig[jOrig]),(hBoundariesOrig[iOrig+1], vBoundariesOrig[jOrig+1]))

          newData[i][j] += overlap(boxCoords, origBoxCoords) * data[iOrig][jOrig] / (hBoundaries[1] * vBoundaries[1])

  return newData



fig = pyplot.figure()
ax1 = fig.add_subplot(1,2,1)
ax2 = fig.add_subplot(1,2,2)

m1, n1 = 37,59
m2, n2 = 10,13

dataGrid1 = numpy.random.rand(m1, n1)
dataGrid2 = meanInterp(dataGrid1, m2, n2)

mat1 = ax1.matshow(dataGrid1, cmap="YlOrRd")
mat2 = ax2.matshow(dataGrid2, cmap="YlOrRd")

#make both plots square
ax1.set_aspect(float(n1)/float(m1))
ax2.set_aspect(float(n2)/float(m2))



pyplot.show()

一个性能友好的实现方式

思路:先对原始数组缩放
再进行插值,线插是我试下来比较满意的,如果你有其他需求请自行更换

这个问题的另一个回答是针对图形的重采样,有兴趣也可以看下

上 代 码 !


import scipy.interpolate as interpolate

def resamplrBylen(orig_list:list,target_len:int):
    '''
    同于标准重采样,此函数将len(list1)=x 从采样为len(list2)=y;y为指定的值,list2为输出
    :param orig_list: 是list,重采样的源列表:list1
    :param target_len: 重采样的帧数:y
    :return: 重采样后的数组:list2
    '''
    orig_list_len =len(orig_list)
    k = target_len/orig_list_len
    x = [x*k for x in range(orig_list_len)]
    x[-1] = 3572740
    if x[-1]!=target_len:
        # 线性更改越界结尾
        x1=x[-2];y1=orig_list[-2];x2=x[-1];y2=orig_list[-1]
        y_resa = (y2 - y1) * (target_len - x1) / (x2 - x1) + y1
        x[-1] = target_len;orig_list[-1]=y_resa
    # 使用了线性的插值方法,也可以根据需要改成其他的。推荐是线性
    f = interpolate.interp1d(x,orig_list,'linear')
    del x
    resample_list = f([x for x in range(target_len)])
    return resample_list