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

时间:2016-06-27 23:18:59

标签: python arrays numpy interpolation

说我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)

另一个例子:

# 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)

2 个答案:

答案 0 :(得分:9)

您可以使用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"')

结果图:

result

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

答案 1 :(得分:2)

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

MWE:

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)

coarse_plot

interp_arr = resampy.resample(short_arr, 20, 100)
plt.plot(interp_arr)

fine_plot
注意两个词:

  1. resampy使用“带限制的正弦插值”。查看文档以获取更多信息。如果您的阵列最初来自具有本地频率分量的数据,例如声音,图像和其他时间序列数据。我在音频上的一些tensorflow示例中使用了它。我不确定您的示例数组是否为演示目的而较小,但是如果确实是数组的大小,则无论您使用线性,样条线还是其他方法,插值都是不好的。

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