Допустим, у меня есть массив истинности массива Numpy, который выглядит примерно так:

truths = [True, False, False, False, True, True]

И у меня есть другой массив значений, который выглядит примерно так:

nums = [1, 2, 3]

Я хочу создать цикл, который заменит все значения истинности в массиве истин на следующее число из массива чисел и заменит все ложные значения на 0.

Я хочу закончить тем, что выглядит следующим образом:

array = [1, 0, 0, 0, 2, 3]
3
k.dav 2 Июл 2019 в 03:25

3 ответа

Лучший ответ

Вы можете использовать cycle из {{X1 }} для циклического просмотра списка nums. Затем просто заархивируйте его своими логическими значениями и используйте троичное понимание списка.

from itertools import cycle  

>>> [num if boolean else 0 for boolean, num in zip(truths, cycle(nums))]
[1, 0, 0, 0, 2, 3]
2
Alexander 2 Июл 2019 в 00:40

Вы можете использовать itertools здесь, как вы сказали, что хотите цикл.

from itertools import cycle, chain, repeat
import numpy as np

truths = np.array([True, False, False, False, True, True])
nums = np.array([1, 2, 3])

#you have 2 options here.
#Either repeat over nums
iter_nums = cycle(nums)
#or when nums is exhausted
#you just put default value in it's place
iter_nums = chain(nums, repeat(0))

masked = np.array([next(iter_nums) if v else v for v in truths])
print(masked)
#[1, 0, 0, 0, 2, 3]
1
Jab 2 Июл 2019 в 00:52

Я бы порекомендовал numpy.putmask(). Так как мы конвертируем из типа bool в int64, сначала нужно сделать несколько конверсий.

Во-первых, инициализация:

truths = np.array([ True, False, False, False,  True,  True])
nums = np.array([1, 2, 3])

Затем мы конвертируем и заменяем на основе нашей маски (если элемент truth равен True):

truths = truths.astype('int64') # implicitly changes all the "False" values to 0
numpy.putmask(truths, truths, nums)

Конечный результат:

>>> truths
array([1, 0, 0, 0, 2, 3])

Обратите внимание, что мы просто передаем truths в аргумент "mask" numpy.putmask(). Это просто проверит, является ли каждый элемент массива truths правдивым; поскольку мы преобразовали массив в тип int64, он заменит только те элементы, которые НЕ равны 0, как требуется.

Если бы мы хотели быть более педантичными или нам нужно было заменить какое-то произвольное значение, нам бы понадобилось numpy.putmask(truths, truths==<value we want to replace>, nums)

Если мы хотим стать ДАЖЕ более педантичным и не делать предположения о том, что мы можем легко конвертировать типы (как мы можем из bool в int64), насколько я знаю, нам либо понадобится сделать какое-то отображение в другой numpy.array, где мы могли бы сделать это преобразование. Я лично сделал бы так, чтобы преобразовать мой numpy.array в некоторый логический массив, где я могу сделать это простое преобразование, но может быть лучший способ.

3
tchainzzz 2 Июл 2019 в 00:39