插入一个numpy数组以适合另一个数组

eri*_*mjl 4 python arrays interpolation numpy

说我有some_data形状(1, n).我有新incoming_data的形状(1, n±x),其中x是一些小于的正整数n.我想挤压或伸展incoming_data,使其长度与之相同n.如何使用SciPy堆栈完成此操作?

这是我想要完成的一个例子.

# Stretch arr2 to arr1's shape while "filling in" interpolated value
arr1 = np.array([1, 5, 2, 3, 7, 2, 1])
arr2 = np.array([1, 5, 2, 3, 7, 1])
result
> np.array([1, 5, 2, 3, 6.x, 2.x 1])  # of shape (arr1.shape)
Run Code Online (Sandbox Code Playgroud)

另一个例子:

# Squeeze arr2 to arr1's shape while placing interpolated value.
arr1 = np.array([1, 5, 2, 3, 7, 2, 1])
arr2 = np.array([1, 5, 2, 3, 4, 7, 2, 1])
result
> np.array([1, 5, 2, 3.x, 7.x, 2.x, 1])  # of shape (arr1.shape)
Run Code Online (Sandbox Code Playgroud)

And*_*eak 10

您可以使用实现此简单压缩或拉伸数据scipy.interpolate.interp1d.我不是说这一定是有道理的(你使用什么样的插值会产生很大的不同,如果你能正确猜出底层函数的行为,你通常只会得到一个合理的结果),但你可以做到这一点.

我们的想法是将原始数组作为x值插入其索引,然后使用较稀疏的x网格执行插值,同时保持其端点相同.因此,基本上您必须对离散数据进行连续近似,并在必要的点重新采样:

import numpy as np
import scipy.interpolate as interp
import matplotlib.pyplot as plt

arr_ref = np.array([1, 5, 2, 3, 7, 1])  # shape (6,), reference
arr1 = np.array([1, 5, 2, 3, 7, 2, 1])  # shape (7,), to "compress"
arr2 = np.array([1, 5, 2, 7, 1])        # shape (5,), to "stretch"
arr1_interp = interp.interp1d(np.arange(arr1.size),arr1)
arr1_compress = arr1_interp(np.linspace(0,arr1.size-1,arr_ref.size))
arr2_interp = interp.interp1d(np.arange(arr2.size),arr2)
arr2_stretch = arr2_interp(np.linspace(0,arr2.size-1,arr_ref.size))

# plot the examples, assuming same x_min, x_max for all data
xmin,xmax = 0,1
fig,(ax1,ax2) = plt.subplots(ncols=2)
ax1.plot(np.linspace(xmin,xmax,arr1.size),arr1,'bo-',
         np.linspace(xmin,xmax,arr1_compress.size),arr1_compress,'rs')
ax2.plot(np.linspace(xmin,xmax,arr2.size),arr2,'bo-',
         np.linspace(xmin,xmax,arr2_stretch.size),arr2_stretch,'rs') 
ax1.set_title('"compress"')
ax2.set_title('"stretch"')
Run Code Online (Sandbox Code Playgroud)

由此产生的情节:

结果

在图中,蓝色圆圈是原始数据点,红色方块是内插数据(这些在边界处重叠).正如您所看到的,我称之为压缩和拉伸实际上是底层(默认情况下为线性)函数的上采样和下采样.这就是为什么我说你必须非常小心插值:如果你的期望与你的数据不符,你会得到非常错误的结果.

  • @ericmjl我很高兴我可以帮忙:)感谢您的反馈.从插值函数推断时要特别小心,这可能导致不受控制的错误.(另外,为了完整性:从scipy版本0.17`interp1d`支持线性插值的外推,使用关键字`full_value ='extrapolate'.). (2认同)

Jak*_*aas 8

还有另一个非常适合上采样和下采样的包:resampy。它的命令比插值函数更简单,scipy.interpolate.interp1d但仅使用单个插值函数。正如@Andras Deak 所说,在选择插值函数时必须小心。

微量元素:

import numpy as np
import resampy
from matplotlib import pyplot as plt

x_mesh = np.linspace(0,1,10)
short_arr = np.sin(x_mesh*2*np.pi)
plt.plot(short_arr)
Run Code Online (Sandbox Code Playgroud)

粗略图

interp_arr = resampy.resample(short_arr, 20, 100)
plt.plot(interp_arr)
Run Code Online (Sandbox Code Playgroud)

精细图
两句警告:

  1. resampy使用“带限正弦插值”。查看文档以获取更多信息。如果您的阵列最初来自具有本地频率分量的数据(例如声音、图像和其他时间序列数据),则效果最佳。它被用在一些关于音频的张量流示例中,这就是我所使用的。我不确定您的示例数组是否出于演示目的而很小,但如果这确实是您的数组的大小,则无论您使用什么方法(线性、样条或其他方法),插值都可能很糟糕。

  2. 您的示例演示的不仅仅是插值。看来您找到了匹配的数组的一部分(例如[1,5,2,3]),然后插入了其余部分。根据您是要匹配数组的开头还是任意数量的补丁,您可能需要两种方法:一种用于识别要插入的数组的正确部分,另一种用于插入这些部分。如果是这种情况,请寻找numpy.isin基本方法或编辑距离,以更普遍地匹配一组子字符串。