堆叠具有索引偏移的数组的简单方法

时间:2016-03-22 15:53:24

标签: python numpy pandas

我有一些时间序列,每个时间序列包含一年中各周的测量值,但并非所有时间序列都在同一周内开始和结束。我知道补偿,我知道每个星期开始和结束的几周。现在我想将它们组合成一个关于固有偏移的矩阵,这样所有的值都将与正确的周数对齐。

如果水平方向包含系列,而垂直方向代表周数,则给定两个系列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)

3 个答案:

答案 0 :(得分:2)

您可以在<beans xmlns="http://www.springframework.org/schema/beans" ... <security:http auto-config="true" use-expressions="true"> <security:form-login login-page="/login" default-target-url="/" login-processing-url="/j_spring_security_check"/> <!-- authentication-failure-url="/login.html?error=true" /> --> <!-- /login.html?error=true --> <!-- default-target-url="/homepage.html" --> <security:csrf disabled="true"/> <security:intercept-url pattern="/login" access="permitAll"/> <!-- <security:intercept-url pattern="/studentRegister" access="permitAll"/> --> <security:intercept-url pattern="/**" access="hasRole('USER')"/> <security:logout logout-success-url="/login?logout=true" invalidate-session="true" delete-cookies="JSESSIONID"/> <security:session-management invalid-session-url="/login"></security:session-management> </security:http> <bean id="userDetailsService" class="bg.jwd.bookmarks.security.UserDetailsServiceImpl" /> <security:authentication-manager> <security:authentication-provider user-service-ref="userDetailsService"> <security:password-encoder hash="md5" /> </security:authentication-provider> </security:authentication-manager> <security:global-method-security secured-annotations="enabled" /> </beans> 中执行:

numpy

答案 1 :(得分:1)

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

你基本上想要填充然后堆叠你的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))
array([[ nan,  nan,  nan,  nan,  nan,  nan,  nan,  nan],
       [ nan,  nan,   1.,   2.,   3.,   4.,   5.,   6.],
       [  0.,   1.,   2.,   3.,   4.,   5.,  nan,  nan],
       [ nan,  nan,  nan,  nan,  nan,  nan,  nan,  nan]])

或用于3d数组:

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)
array([[[ nan,   0.],
        [  1.,   1.],
        [  2.,   2.],
        [  3.,  nan]]])

答案 2 :(得分:1)

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