使用索引偏移量堆叠数组的简单方法



我有很多时间序列,每个时间序列都包含一年中几周的测量值,但并非所有时间序列都在同一周开始和结束。我知道补偿,也就是说,我知道每一周的开始和结束时间。现在我想把它们组合成一个矩阵,尊重固有的偏移量,这样所有的值都将与正确的周数对齐。

如果水平方向包含系列,垂直方向表示周,则给定两个系列ab,其中的值对应于周数:

a = np.array([[1,2,3,4,5,6]])
b = np.array([[0,1,2,3,4,5]])

我想知道是否有可能将它们组合在一起,例如,使用某种方法,以combine((a, b), axis=0, offset=-1)这样的方式接受偏移参数,这样得到的数组(让我们称之为c)看起来像这样:

print c
[[NaN 1   2   3   4   5   6  ]
 [0   1   2   3   4   5   NaN]]

更重要的是,由于时间序列是巨大的,我必须通过我的程序流式传输它们,因此不能同时知道所有的偏移量。我想到使用Pandas是因为它有很好的索引,但我觉得必须有一种更简单的方法,因为我试图做的事情的本质是超级简单的。

更新:这似乎工作

def offset_stack(a, b, offset=0):
    if offset < 0:
        a = np.insert(a, [0] * abs(offset), np.nan)
        b = np.append(b, [np.nan] * abs(offset))
    if offset > 0:
        a = np.append(a, [np.nan] * abs(offset))
        b = np.insert(b, [0] * abs(offset), np.nan)
    return np.concatenate(([a],[b]), axis=0)

您可以在numpy:中执行

def f(a, b, n):
    v = np.empty(abs(n))*np.nan
    if np.sign(n)==-1:
        return np.vstack((np.append(a,v), np.append(v,b)))
    elif np.sign(n)==1:
        return np.vstack((np.append(v,a), np.append(b,v)))
    else:
        return np.vstack((a,b))
#In [148]: a = np.array([23, 13, 4, 12, 4, 4])
#In [149]: b = np.array([4, 12, 3, 41, 45, 6])
#In [150]: f(a,b,-2)
#Out[150]:
#array([[ 23.,  13.,   4.,  12.,   4.,   4.,  nan,  nan],
#       [ nan,  nan,   4.,  12.,   3.,  41.,  45.,   6.]])
#In [151]: f(a,b,2)
#Out[151]:
#array([[ nan,  nan,  23.,  13.,   4.,  12.,   4.,   4.],
#       [  4.,  12.,   3.,  41.,  45.,   6.,  nan,  nan]])
#In [152]: f(a,b,0)
#Out[152]:
#array([[23, 13,  4, 12,  4,  4],
#       [ 4, 12,  3, 41, 45,  6]])

有一种真正简单的方法可以实现这一点。

你基本上想填充然后堆叠你的arrays,两者都有numpy函数:

numpy.lib.pad()又名偏移

a = np.array([[1,2,3,4,5,6]], dtype=np.float_) # float because NaN is a float value!
b = np.array([[0,1,2,3,4,5]], dtype=np.float_)
from numpy.lib import pad
print(pad(a, ((0,0),(1,0)), mode='constant', constant_values=np.nan))
# [[ nan   1.   2.   3.   4.   5.   6.]]
print(pad(b, ((0,0),(0,1)), mode='constant', constant_values=np.nan))
# [[  0.,   1.,   2.,   3.,   4.,   5.,  nan]]

((0,0)(1,0))意味着在第一轴(顶部/底部)上没有填充,并且只在左侧填充一个元素而在右侧没有元素。所以,如果你想要更多/更少的转变,你必须调整这些。

numpy.vstack(),即沿轴堆叠=0

import numpy as np
a_padded = pad(a, ((0,0),(1,0)), mode='constant', constant_values=np.nan)
b_padded = pad(b, ((0,0),(0,1)), mode='constant', constant_values=np.nan)
np.vstack([a_padded, b_padded])
# array([[ nan,   1.,   2.,   3.,   4.,   5.,   6.],
#        [  0.,   1.,   2.,   3.,   4.,   5.,  nan]])

您的功能:

将这两者结合起来将非常容易,并且易于扩展:

from numpy.lib import pad
import numpy as np
def offset_stack(a, b, axis=0, offsets=(0, 1)):
    if (len(offsets) != a.ndim) or (a.ndim != b.ndim):
        raise ValueError('Offsets and dimensions of the arrays do not match.')
    offset1 = [(0, -offset) if offset < 0 else (offset, 0) for offset in offsets]
    offset2 = [(-offset, 0) if offset < 0 else (0, offset) for offset in offsets]
    a_padded = pad(a, offset1, mode='constant', constant_values=np.nan)
    b_padded = pad(b, offset2, mode='constant', constant_values=np.nan)
    return np.concatenate([a_padded, b_padded], axis=axis)
offset_stack(a, b)

该函数适用于任意维度中的广义偏移,并且可以在任意维度中堆叠。它的工作方式与原始的不同,因为您填充刚刚通过offset=1的第二个维度将填充第一个维度。但是,如果您跟踪数组的维度,它应该可以正常工作。

例如:

offset_stack(a, b, offsets=(1,2))
阵列([[nan,nan,nan,nan,[楠,楠,1.,2.,3.,4.,5.,6.],[0.,1.,2.,3.,4.,5.,nan,nan],[楠,楠,楠

或用于三维阵列:

a = np.array([1,2,3], dtype=np.float_)[None, :, None] # makes it 3d
b = np.array([0,1,2], dtype=np.float_)[None, :, None] # makes it 3d
offset_stack(a, b, offsets=(0,1,0), axis=2)
数组([[nan,0.],[1.,1.],[2.,2.],[3])

padconcatenate(以及各种堆栈和插入)创建一个合适大小的目标数组,并填充输入数组中的值。因此,我们可以做同样的事情,而且可能做得更快。

例如,使用2个阵列和1步偏移:

In [283]: a = np.array([[1,2,3,4,5,6]])
In [284]: b = np.array([[0,1,2,3,4,5]])

创建目标数组,并用pad值填充它。np.nan是浮点(即使a是int):

In [285]: m=a.shape[0]+b.shape[0]    
In [286]: n=a.shape[1]+1    
In [287]: c=np.zeros((m,n),float)
In [288]: c.fill(np.nan)

现在只需将值复制到目标上的正确位置即可。在这里,更多的数组和偏移将需要一些泛化。

In [289]: c[:a.shape[0],1:]=a
In [290]: c[-b.shape[0]:,:-1]=b
In [291]: c
Out[291]: 
array([[ nan,   1.,   2.,   3.,   4.,   5.,   6.],
       [  0.,   1.,   2.,   3.,   4.,   5.,  nan]])

最新更新