Массив numpy фильтра Python на основе массива масок

#python #arrays #numpy

Вопрос:

Допустим, у меня есть массив данных numpy длиной N и массив битовых масок длиной N.

 data = [1,2,3,4,5,6,7,8,9,0]
mask = [0,1,0,1,0,1,0,1,0,1]
 

Существует ли безцикловый способ создания нового массива на основе данных, такой, чтобы он принимал все записи данных тогда и только тогда, когда маски[i] != 0? Вот так:

 func(data, mask) = [2,4,6,8,0]
 

Или, что эквивалентно, в циклической нотации:

 ans = []
for idx in range(mask):
    if mask[idx]:
        ans.append(data[idx])
ans = numpy.array(ans)
 

Спасибо!

Комментарии:

1. Ваш вопрос еще проще, чем связанный дубликат, поскольку вы работаете только в одном измерении. необходимый код… подождите его… data[mask != 0] . И да, такого рода упрощение является одним из основных преимуществ Numpy. Конечно, вам нужно начинать с массивов Numpy, а не с простых списков Python.

2. Вы должны проверить: numpy doc с решением . В вашем случае просто сделайте: np.ma.array(data, mask=mask).data (измените список на массивы раньше).

3. @Memristor когда я пытаюсь np.ma.array(data, mask=mask).data , я просто получаю исходный массив. На самом деле не совсем ясно, как ссылку, которую вы разместили, можно использовать для получения результатов, которые хочет получить ОП.

4. Да, похоже .data , это дает вам исходный массив. .tolist() дает вам замаскированный список, но не удаляет замаскированные значения. Они всегда заполнены fill_value (либо None или пользовательским значением).

5. @MarkM извините, вы должны получить результат x = np.ma.array(...) , а затем x[~x.mask].data он удаляет элементы с маской 0; Другой способ заключается в использовании where : np.where([1, 0, 1, 0, 1], [1, 2, 3, 4, 5], 0) это не удаляет их, а заменяет 0.

Ответ №1:

Вы можете фильтровать массивы numpy с помощью массива логических значений. Вы начинаете с массива целых чисел, которые вы не можете использовать напрямую, но вы, конечно, можете интерпретировать единицы и нули как логические значения, а затем использовать их непосредственно в качестве маски:

 import numpy as np

data = np.array([1,2,3,4,5,6,7,8,9,0])
mask = np.array([0,1,0,1,0,1,0,1,0,1])

data[mask.astype(bool)]
# array([2, 4, 6, 8, 0])