Pandas掩码列表的逻辑或运算

7

我有一个由不同搜索条件应用于数据帧而获得的布尔掩码列表。这里是一个包含4个掩码的示例列表:

mask_list = [mask1, mask2, mask3, mask4]

我希望能够找到列表中所有掩码的逻辑或。换句话说,需要对这些掩码进行位运算,得到一个结果。
or_mask = mask_list[0] | mask_list[1] | mask_list[2] | mask_list[3]

有没有一种简洁的方法来处理包含任意数量掩码的列表?我知道可以编写以下for循环,但是否有更短、更Pythonic的方法呢?

for i in range(len(mask_list)):
    if i == 0:
        temp_mask_or = mask_list[i]
    else:
        temp_mask_or = temp_mask_or | mask_list[i]
2个回答

8
你可以使用reduce: or_(x,y)的意思是x|y,因此这将起作用:
from operator import or_
or_mask = reduce(or_,mask_list)

编辑:如JoeCondron建议的那样,你可以使用numpy.logical_or代替operator.or_,这样可以得到相同的结果但速度更快。


我之前不知道这些命令,谢谢你的启示! - alwaysCurious
6
您也可以使用numpy.logical_or代替or_,看起来它的速度大约快4-6倍。 - JoeCondron
我已经构建了两个掩码,其中一个包含NaN,因此被认为是dtype对象。使用operator.or_减少掩码时,就好像NaN是False一样。使用numpy.logical_or使得结果掩码成为dtype对象,然后进行掩码处理会导致ValueError:Cannot mask with non-boolean array containing NA / NaN values。(最初我尝试过np.any(masks, axis=0),但结果也是同样的错误。) - bli

2

当我合并掩码时,通常会使用与你类似的循环,但可能略有不同:

combmask = mask_list[0]
for mask in mask_list[1:]:
    combmask |= mask

如果还不够简短,你可以利用只进行运算的事实,将它们视为整数(在底层下是这样的),以此来简化操作:
combmask = np.array(sum(mask_list), dtype=np.bool)

如果你看一下sum(mask_list),你会发现它只是一个整数列表。
可能有一个潜在的问题,就是我不知道后一种方法是否会在尝试对255个以上的掩码求和时遇到问题,其中至少一个元素始终为True(即1)。据我所知,存储np.bool的底层整数类型只有8位,这样你将达到整数限制。也许numpy/Python在继续之前会自动将所有内容转换为16位整数类型,但我不确定。

编辑:我会保留后面的提及,但很容易检查:

In [51]: len(mask_list)
Out[51]: 4

In [52]: sum(mask_list).dtype
Out[52]: dtype('int64')

因此,即使是短掩码列表的总和也会转换为64位整数(然后可以轻松地转换为布尔掩码数组),而且您不会轻易遇到整数限制。


是的,我更喜欢你的for循环。关于掩码只是整数列表的部分非常有趣 - 我不知道那个。 - alwaysCurious

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接