如何在Numpy中将索引数组转换为掩码数组?

39

如何将给定范围内的索引数组转换为0和1的数组呢? 例如:[2,3] -> [0, 0, 1, 1, 0],范围为5

我想要自动化类似这样的过程:

>>> index_array = np.arange(200,300)
array([200, 201, ... , 299])

>>> mask_array = ???           # some function of index_array and 500
array([0, 0, 0, ..., 1, 1, 1, ... , 0, 0, 0])

>>> train(data[mask_array])    # trains with 200~299
>>> predict(data[~mask_array]) # predicts with 0~199, 300~499

scipy有一个掩码数组模块。它与这个问题有关。http://docs.scipy.org/doc/numpy/reference/maskedarray.html - K.Chen
1
[x in index_array for x in range(500)] 这样做可以实现,但是返回的是 TrueFalse 而不是 1 和 0。 - genisage
@genisage,您能否把您的评论作为答案?我想选择您的答案。这正是我在寻找的东西。感谢您的回答! - Efreeto
numpy.array([boolean_value in indices for x in range(length)], dtype=np.int8) 可以用于一维数组。 - Max Collier
不确定是否直接与上面提出的问题相关,但您是否探索过numpy masked_array https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.ma.array.html,以便进行进一步的探索。 - Pramit
4个回答

47

这是一种方法:

In [1]: index_array = np.array([3, 4, 7, 9])

In [2]: n = 15

In [3]: mask_array = np.zeros(n, dtype=int)

In [4]: mask_array[index_array] = 1

In [5]: mask_array
Out[5]: array([0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0])

如果口罩始终是一个范围,您可以消除 index_array ,并将 1 分配给一个切片:

In [6]: mask_array = np.zeros(n, dtype=int)

In [7]: mask_array[5:10] = 1

In [8]: mask_array
Out[8]: array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0])
如果您想要一个布尔值数组而不是整数数组,创建 mask_array 时更改其 dtype 即可:
In [11]: mask_array = np.zeros(n, dtype=bool)

In [12]: mask_array
Out[12]: 
array([False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False], dtype=bool)

In [13]: mask_array[5:10] = True

In [14]: mask_array
Out[14]: 
array([False, False, False, False, False,  True,  True,  True,  True,
        True, False, False, False, False, False], dtype=bool)

1
+1 这也是一个非常好的答案,特别是如果有人想让他们的mask_array成为np.array。 - Efreeto
它比列表推导式更高效。 - JulienD
1
使用int而不是bool有什么优势吗?我只是想知道为什么答案的前半部分在问题要求掩码时没有推荐bool。 - AnnanFay

14

对于一个单一的维度,请尝试:

n = (15,)
index_array = [2, 5, 7]
mask_array = numpy.zeros(n)
mask_array[index_array] = 1

对于多维数组,将n维索引转换为一维索引,然后使用ravel函数:

n = (15, 15)
index_array = [[1, 4, 6], [10, 11, 2]] # you may need to transpose your indices!
mask_array = numpy.zeros(n)
flat_index_array = np.ravel_multi_index(
    index_array,
    mask_array.shape)
numpy.ravel(mask_array)[flat_index_array] = 1

2

有一个不错的技巧可以把这个做成一行代码 - 使用 numpy.in1dnumpy.arange 函数,像这样(最后一行是关键部分):

>>> x = np.linspace(-2, 2, 10)
>>> y = x**2 - 1
>>> idxs = np.where(y<0)

>>> np.in1d(np.arange(len(x)), idxs)
array([False, False, False,  True,  True,  True,  True, False, False, False], dtype=bool)

这种方法的缺点是它比Warren Weckesser提供的方法慢了约10-100倍......但它只有一行代码,这可能或可能不是你想要的。

in1d()方法不是比其他提出的解决方案都更昂贵吗? - Johann Bzh

1

根据要求,这是答案中的代码:

[x in index_array for x in range(500)]

这将会给你一个像你要求的那样的掩码,但它将使用布尔值而不是0和1。


这是原始提问者最初标记的答案。但是标记它会导致其他人投反对票达到-3,所以我不得不更改我的标记... - Efreeto
这个很慢:它不仅没有向量化,而且还是O(n²)的。 - Kyuuhachi

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