Reputation: 59
Let's say I have a Numpy array truth array that looks something like the following:
truths = [True, False, False, False, True, True]
and I have another array of values that looks something like:
nums = [1, 2, 3]
I want to create a loop that will replace all the truth values in the truths array with the next number from the nums array and replace all the False values with 0.
I want to end up with something that looks like:
array = [1, 0, 0, 0, 2, 3]
Upvotes: 3
Views: 1342
Reputation: 27485
You could use itertools
here as you said you want a loop.
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]
Upvotes: 1
Reputation: 109546
You can use cycle
from itertools
to cycle through your nums
list. Then just zip it with your booleans and use a ternary list comprehension.
from itertools import cycle
>>> [num if boolean else 0 for boolean, num in zip(truths, cycle(nums))]
[1, 0, 0, 0, 2, 3]
Upvotes: 2
Reputation: 915
I would recommend numpy.putmask()
. Since we're converting from type bool
to int64
, we need to do some conversions first.
First, initialization:
truths = np.array([ True, False, False, False, True, True])
nums = np.array([1, 2, 3])
Then we convert and replace based on our mask (if element of truth
is True):
truths = truths.astype('int64') # implicitly changes all the "False" values to 0
numpy.putmask(truths, truths, nums)
The end result:
>>> truths
array([1, 0, 0, 0, 2, 3])
Note that we just pass in truths
into the "mask" argument of numpy.putmask()
. This will simply check to see if each element of array truths
is truthy; since we converted the array to type int64
, it will replace only elements that are NOT 0, as required.
If we wanted to be more pedantic, or needed to replace some arbitrary value, we would need numpy.putmask(truths, truths==<value we want to replace>, nums)
instead.
If we want to go EVEN more pedantic and not make the assumption that we can easily convert types (as we can from bool
to int64
), as far as I'm aware, we'd either need to make some sort of mapping to a different numpy.array
where we could make that conversion. The way I'd personally do that is to convert my numpy.array
into some boolean array where I can do this easy conversion, but there may be a better way.
Upvotes: 3