tags:

views:

225

answers:

3

Hi, Currently I have a code that checks if given element in array is equal = 0 and if so then set the value to 'level' value (temp_board is 2D numpy array, indices_to_watch contains 2D coordinates that should be watched for zeros).

    indices_to_watch = [(0,1), (1,2)]
    for index in indices_to_watch:
        if temp_board[index] == 0:
            temp_board[index] = level

I would like to convert this to a more numpy-like approach (remove the for and use only numpy functions) to speed this up. Here's what I tried:

    masked = np.ma.array(temp_board, mask=(a!=0), hard_mask=True)
    masked.put(indices_to_watch, level)

But unfortunately masked array when doing put() wants to have 1D dimensions (totally strange!), is there some other way of updating array elements that are equal to 0 and have concrete indices?

Or maybe using masked arrays is not the way to go?

A: 

You should try something along those lines:

temp_board[temp_board[field_list] == 0] = level
Olivier
unfortunately temp_board[field_list] == 0 returns a mask that is smaller than the size of temp_board
krzyk
A: 

I'm not sure i follow all of the detail in your question. If i understood it correctly, then it seems like this is straightforward Numpy indexing. The code below checks the array (A) for zeros, and where it finds them, it replaces them with 'level'.

import numpy as NP
A = NP.random.randint(0, 10, 20).reshape(5, 4) 
level = 999
ndx = A==0
A[ndx] = level
doug
+1  A: 

Assuming that it is not very inefficient to find out where temp_board is 0, you can do what you want like this:

# First figure out where the array is zero
zindex = numpy.where(temp_board == 0)
# Make a set of tuples out of it
zindex = set(zip(*zindex))
# Make a set of tuples from indices_to_watch too
indices_to_watch = set([(0,1), (1,2)])
# Find the intersection.  These are the indices that need to be set
indices_to_set = indices_to_watch & zindex
# Set the value
temp_board[zip(*indices_to_set)] = level

If you can't do the above, then here's a way, but I am not sure if it's the most Pythonic:

indices_to_watch = [(0,1), (1,2)]

First, convert to a numpy array:

indices_to_watch = numpy.array(indices_to_watch)

Then, make it indexable:

index = zip(*indices_to_watch)

Then, test the condition:

indices_to_set = numpy.where(temp_board[index] == 0)

Then, figure out the actual indices to set:

final_index = zip(*indices_to_watch[indices_to_set])

Finally, set the values:

temp_board[final_index] = level
Alok
Thank you :)I tried numpy.where() but didn't think of combining it with set intersection
krzyk