python/numpy:对切片求反或求补
我有一些函数,是大型分析软件的一部分,它们需要一个布尔掩码来将数组项分成两组。这些功能如下所示:python/numpy:对切片求反或求补,python,arrays,numpy,slice,Python,Arrays,Numpy,Slice,我有一些函数,是大型分析软件的一部分,它们需要一个布尔掩码来将数组项分成两组。这些功能如下所示: 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,并且不传递带有allTrue的布尔掩
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,并且不传递带有allTrue
的布尔掩码。例如,我可以传递一个切片,如slice(None,None)
问题是,如果a\u mask
是片,那么b\u mask=-a\u mask
行将失败。理想情况下,-一个_掩码
应该给出一个0项选择
我正在考虑创建一个“修改的”切片对象,该对象将\uuuu neg\uuuu()方法实现为空切片(例如slice(0,0)
)。我不知道这是否可能
其他不允许修改process()
函数,但同时避免分配全真布尔数组的解决方案也将被接受。不幸的是,我们无法将\uuu neg\uuu()
方法添加到切片
。但是,tuple
可以被子类化,我们可以使用它来保存单个切片
对象
这让我想到了一个非常非常恶劣的黑客行为,这对你来说应该很有用:
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]
# []
然而,你必须非常绝望地求助于这样的事情。这样修改过程是完全不可能的吗
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
这是一种更加明确的方式,对于您当前的用例来说,不应该对其行为产生任何影响。您的解决方案非常类似于退化稀疏布尔数组,尽管我不知道有任何相同的实现。我下意识的反应是不喜欢,但如果你真的不能修改过程,这可能是最好的方法。如果你担心内存使用,那么高级索引可能是个坏主意。从
高级索引始终返回数据的副本(与返回视图的基本切片不同)
目前,过程
功能具有:
数据
大小n
say
a_掩码
大小n
(假设采用高级索引)
并创造:
b_掩码
大小n
数据[a_mask]
大小m
say
数据[b_掩码]
大小n-m
这实际上是4个大小为n
的数组
基本切片似乎是最好的选择,但是Python似乎不允许子类化slice
:
TypeError: Error when calling the metaclass bases
type 'slice' is not an acceptable base type
请参阅@ali_m的答案,了解包含切片的解决方案
或者,您可以绕过过程
,将结果作为
result = func_a(data), func_b([])
OP正在寻找一个不改变过程的解决方案
@PeterGibson,而我的判断更好我已经用这样一个解决方案更新了我的答案,这个解决方案真的很可怕,但在提供一个有效的解决方案方面做得很好:)我同意这并不漂亮,但过程
功能实际上相当复杂,分析的很大一部分取决于它的正确性。我宁愿对这个特定的用例进行黑客攻击,也不愿意冒着弄乱其他(已经过良好测试的)用例的风险。谢谢。随你的便,但如果我是你,我会更担心黑客可能出了什么问题。你的过程
函数有多复杂其实并不重要——最终,所有的更改都将相当于一个关键字参数和5或6行新行来处理条件。什么是退化的稀疏布尔数组,以及它如何避免创建全真布尔数组?@user2304916稀疏矩阵压缩某些值(通常为0)。布尔稀疏矩阵可以很容易地编写,以压缩构成多数的任何值(真或假)。你的是退化的,因为它只适用于全零或全一的矩阵。是的,一个布尔稀疏矩阵可以压缩真或假。在scipy/numpy IMHO中有这样一个野兽会很好。是的,但是有时候,奇特的索引是唯一的方法(如果目标元素的间距不规则,等等)。不幸的是,我不能在这里使用基本切片,因为这两个组的元素是无序的。感谢您深入了解使用布尔掩码的内存使用情况。@user2304916是的,对于一般用途,我可以看出布尔掩码是必要的。我指的是你问题中的案例,切片是合适的。