Python在滚动窗口中操作多个数据阵列

时间:2011-08-07 16:25:47

标签: python arrays numpy

考虑以下代码:

class MyClass(object):

    def __init__(self):

        self.data_a = np.array(range(100))
        self.data_b = np.array(range(100,200))
        self.data_c = np.array(range(200,300))

    def _method_i_do_not_have_access_to(self, data, window, func):

        output = np.empty(np.size(data))

        for i in xrange(0, len(data)-window+1):
            output[i] = func(data[i:i+window])

        output[-window+1:] = np.nan

        return output

    def apply_a(self):

        a = self.data_a

        def _my_func(val):
            return sum(val)

        return self._method_i_do_not_have_access_to(a, 5, _my_func)

my_class = MyClass()
print my_class.apply_a()

_method_i_do_not_have_access_to方法采用numpy数组,窗口参数和用户定义的函数句柄,并返回一个数组,该数组包含window数据点上的函数句柄输出的值。输入数据数组 - 通用滚动方法。我无权更改此方法。

如您所见,_method_i_do_not_have_access_to将一个输入传递给函数句柄,该句柄是传递给_method_i_do_not_have_access_to的数据数组。该函数句柄仅计算通过window传递给它的一个数据数组上基于输出的_method_i_do_not_have_access_to数据点。

我需要做的是允许_my_func(传递给_method_i_do_not_have_access_to的函数句柄)对data_bdata_c进行操作以及传递给的数组_my_func_method_i_do_not_have_access_to window索引 data_bdata_c全局定义在MyClass class

我想到这样做的唯一方法就是在data_b中引用data_c_my_func,如下所示:

def _my_func(val):
    b = self.data_b
    c = self.data_c
    # do some calculations
    return sum(val)

但是,我需要将bc切片到与val相同的索引(请记住val是数组的长度 - window切片这是通过_method_i_do_not_have_access_to)传递的。

例如,如果_method_i_do_not_have_access_to中的循环当前正在输入数组上的索引45 -> 50上运行,则_my_func必须在b上的相同索引上运行, c

最终结果将是这样的:

def _my_func(val):

    b = self.data_b # somehow identify which slide we are at
    c = self.data_c # somehow identify which slide we are at

    # if _method_i_do_not_have_access_to is currently
    # operating on indexes 45->50, then the sum of 
    # val, b, and c should be the sum of the values at
    # index 45->50 at each

    return sum(val) * sum(b) + sum(c)

关于如何实现这一目标的任何想法?

4 个答案:

答案 0 :(得分:1)

问题是_my_func将如何知道哪些操作?如果在调用函数时事先知道了indizes,最简单的方法就是使用lambda:lambda val: self._my_func(self.a, self.b, index, val),其中_my_func明显改变以容纳其他参数。

由于你不知道indizes,你必须编写一个围绕self.c的包装器来记住上次访问哪个索引(或者更好地捕获切片操作符)并将其存储在一个变量中以便你的函数使用..

编辑:敲了一个小例子,不是特别好的编码风格和所有,但应该给你的想法:

class Foo():
    def __init__(self, data1, data2):
        self.data1 = data1
        self.data2 = data2
        self.key = 0      

    def getData(self):
        return Foo.Wrapper(self, self.data2)

    def getKey(self):
        return self.key

    class Wrapper():
        def __init__(self, outer, data):
            self.outer = outer
            self.data = data

        def __getitem__(self, key):
            self.outer.key = key
            return self.data[key]

if __name__ == '__main__':
    data1 = [10, 20, 30, 40]
    data2 = [100, 200, 300, 400]
    foo = Foo(data1, data2)
    wrapped_data2 = foo.getData()
    print(wrapped_data2[2:4])
    print(data1[foo.getKey()])

答案 1 :(得分:1)

您可以将二维数组传递给_method_i_do_not_have_access_to()。 len()和切片操作将适用于它:

In [29]: a = np.arange(100)
In [30]: b = np.arange(100,200)
In [31]: c = np.arange(200,300)
In [32]: data = np.c_[a,b,c] # make your three one dimension array to one two dimension array.

In [35]: data[0:10] # slice operation works.
Out[35]:
array([[  0, 100, 200],
       [  1, 101, 201],
       [  2, 102, 202],
       [  3, 103, 203],
       [  4, 104, 204],
       [  5, 105, 205],
       [  6, 106, 206],
       [  7, 107, 207],
       [  8, 108, 208],
       [  9, 109, 209]])

In [36]: len(data) # len() works.
Out[36]: 100

In [37]: data.shape
Out[37]: (100, 3)

所以您可以按如下方式定义_my_func:

def _my_func(val):
    s = np.sum(val, axis=0)
    return s[0]*s[1] + s[2]

答案 2 :(得分:0)

这是一个黑客:

创建一个具有DataProxy方法的新类__getitem__,并代理三个数据数组(例如,在初始化时可以传递给它)。创建func act on DataProxy实例而不是标准的numpy数组,并将修改后的func和代理传递给不可访问的方法。

这有意义吗?这个想法是data没有约束成为一个数组,只是为了可订阅。因此,您可以使用自定义的可订阅类来代替数组。


示例:

class DataProxy:
    def __init__(self, *data):
        self.data = list(zip(*data))

    def __getitem__(self, item):
        return self.data[item]

然后创建一个新的DataProxy,在您执行此操作时传入任意数量的数组,并使func接受索引所述实例的结果。试试吧!

答案 3 :(得分:0)

由于_method_i_do_not..似乎只是将您的函数应用于您的数据,您是否可以将数据精确地放在索引数组中?然后,func会使用索引进行data_adata_bdata_c的窗口访问。可能有更快的方法,但我认为这将以最小的复杂性起作用。

换句话说,大致相同的事情,如有必要,在window添加额外处理:

def apply_a(self):

    a = self.data_a
    b = self.data_b
    c = self.data_c

    def _my_func(window):
        return sum(a[window]) * sum(b[window]) + sum(c[window])

    return self._method_i_do_not_have_access_to(window_indices, 5, _my_func)