5

I've read through most of How to convert a boolean array to an int array , but I was still at loss with, how to (most efficiently) convert a numpy bool array to an int array, but with distinct values. For instance, I have:

>>> k=np.array([True, False, False, True, False])
>>> print k
[ True False False  True False]

I'd like this to be converted to an array, where True is say, 2, and False is say 5.

Of course, I can always set up a linear equation:

>>> print 5-k*3
[2 5 5 2 5]

... which, while vectorized, needlessly employs both addition (subtraction) and multiplication; furthermore, if I'd want the opposite values (5 for True and 2 for False), I basically have to use (and recalculate) a different equation:

>>> print 2+k*3
[5 2 2 5 2]

... which is a bit of a readability issue for me.

In essence, this is merely a selection/mapping operation - but one which I'd like done in the numpy domain. How could I do that?

Community
  • 1
  • 1
sdaau
  • 36,975
  • 46
  • 198
  • 278

2 Answers2

10

Seems like numpy.where is exactly what you want:

>>> import numpy as np
>>> k = np.array([True, False, False, True, False])
>>> np.where(k, 2, 5)
array([2, 5, 5, 2, 5])
mgilson
  • 300,191
  • 65
  • 633
  • 696
  • Fantastic - thanks a lot, @mgilson! Actually, was looking for something that would work in a recursive `np.add` (but didn't mention that, because I wanted to reduce the question to "bare essentials" ), this looks like it will do the trick! Thanks again - cheers! – sdaau Dec 19 '13 at 02:55
  • PS: re: "recursive add", now that I've mentioned it (even if it is a bit off-topic for this question): anytime one has _anything else_ other than the "raw" reference in arguments, even just addition, e.g. in `a=np.array([1,3,3,4,5,6]); np.add(a[:-1]+0, 2, a[1:]); print a` -- numpy will use the "old" values for `a[:-1]` (in the `a[:-1]+0`) and will _not_ "recurse" to the "new" previous locations; thus, `np.where` (and probably any other function) will have the same effect. – sdaau Dec 19 '13 at 06:27
1

Well, it seems I have to make a np.array (not a Python list!) containing the two distinct values:

>>> z=np.array([2,5])
>>> print z
[2 5]

... and then I can simply cast the boolean array (k) to int, and use that as selection indices in the "distinct values array" (z):

>>> print z[k.astype(int)]
[5 2 2 5 2]

It is also trivial to change the [2,5] to [5,2], so that is good.

I'm just not sure if this is the right way to do it (that is, maybe there exists something like (pseudocode) k.asdistinctvalues([2,5]) or something like that?)

sdaau
  • 36,975
  • 46
  • 198
  • 278
  • 1
    Going for the sock puppet hat I see? Good move. I need to figure out something to ask a question about too ... ;-) – mgilson Dec 19 '13 at 02:48
  • Heh - honestly, sometimes when I get frustrated of not being able to find an approach with my search terms, I do document stuff on SO in Q&A format, so I can find it next time I type it in a search engine; hope that's not a crime. Cheers! `:)` – sdaau Dec 19 '13 at 02:57
  • 1
    Clearly it isn't a crime, they're even giving incentives to do it -- They've chosen to reward the behavior with a hat! – mgilson Dec 19 '13 at 06:02