考虑以下代码:
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_b
和data_c
进行操作以及传递给的数组_my_func
到_method_i_do_not_have_access_to
的window
索引 。 data_b
和data_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)
但是,我需要将b
和c
切片到与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)
关于如何实现这一目标的任何想法?
答案 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_a
,data_b
和data_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)