我有很多时间序列,每个时间序列都包含一年中几周的测量值,但并非所有时间序列都在同一周开始和结束。我知道补偿,也就是说,我知道每一周的开始和结束时间。现在我想把它们组合成一个矩阵,尊重固有的偏移量,这样所有的值都将与正确的周数对齐。
如果水平方向包含系列,垂直方向表示周,则给定两个系列a
和b
,其中的值对应于周数:
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])
pad
和concatenate
(以及各种堆栈和插入)创建一个合适大小的目标数组,并填充输入数组中的值。因此,我们可以做同样的事情,而且可能做得更快。
例如,使用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]])