我有一些功能,是大分析软件的一部分,需要一个布尔掩码来将数组项分成两组。这些功能是这样的:
def process(data, a_mask):
b_mask = -a_mask
res_a = func_a(data[a_mask])
res_b = func_b(data[b_mask])
return res_a, res_b
现在,我需要使用这些函数(没有修改)和一个只有类“a”的项目的大数组,但我想保存RAM并且不传递所有{{1}的布尔掩码}。例如,我可以传递像True
这样的切片。
问题是如果slice(None, None)
是切片,则行b_mask = -a_mask
将失败。理想情况下a_mask
应该给出0项选择。
我正在考虑创建一个“修改过的”切片对象,该对象将-a_mask
方法实现为空切片(例如__neg__()
)。我不知道这是否可能。
其他允许不修改slice(0, 0)
函数但同时避免分配全True布尔数组的解决方案也将被接受。
答案 0 :(得分:1)
很遗憾,我们无法向__neg__()
添加slice
方法,因为它cannot be subclassed。但是,tuple
可以是子类,我们可以使用它来保存单个slice
对象。
这引出了一个非常非常讨厌的黑客攻击,它应该适合你:
class NegTuple(tuple):
def __neg__(self):
return slice(0)
我们可以创建一个包含单个切片对象的NegTuple
:
nt = NegTuple((slice(None),))
这可以用作索引,否则它将产生一个空切片,导致0长度数组被索引:
a = np.arange(5)
print a[nt]
# [0 1 2 3 4]
print a[-nt]
# []
但是,你必须非常渴望诉诸这样的事情。完全不可能像这样修改process
吗?
def process(data, a_mask=None):
if a_mask is None:
a_mask = slice(None) # every element
b_mask = slice(0) # no elements
else:
b_mask = -a_mask
res_a = func_a(data[a_mask])
res_b = func_b(data[b_mask])
return res_a, res_b
这种方式更明确,不应对其当前用例的行为产生任何影响。
答案 1 :(得分:0)
你的解决方案非常类似于简并稀疏布尔数组,尽管我不知道它的任何实现。我的下意识反应是不喜欢的,但如果你真的无法修改process
,这可能是最好的方法。
答案 2 :(得分:0)
如果您担心内存使用,那么高级索引可能不是一个好主意。来自docs
高级索引始终返回数据的副本(与返回视图的基本切片形成对比)。
目前,process
函数有:
data
大小n
说a_mask
,大小为n
(假设为高级索引)创造:
b_mask
,大小为n
data[a_mask]
大小m
说data[b_mask]
,大小为n - m
这实际上是4个大小为n
的数组。
基本切片似乎是你最好的选择,但是Python似乎不允许继承slice
:
TypeError: Error when calling the metaclass bases
type 'slice' is not an acceptable base type
请参阅@ ali_m的答案,了解包含切片的解决方案。
或者,您可以绕过process
并将结果作为
result = func_a(data), func_b([])