k.dav
k.dav

Reputation: 59

Looping through a Truth array in python and replacing true values with components from another array

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

Answers (3)

Jab
Jab

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

Alexander
Alexander

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

chang_trenton
chang_trenton

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

Related Questions