简体   繁体   中英

Apply function to 2D numpy array elements

I've seen this post and want to do something similar, but not exactly the same.

I am implementing a little game of life game and using numpy arrays for representing the states of the game. So I need to check, how many alive neighbors a cell has. I already got a function for getting a window of neighbors given a coordinate and row count and column count for the window size that I want to have.

So usually my windows will be of 3x3 size like this:

T = True
F = False
[[T,T,T],
 [F,T,T],
 [F,F,F]]  # some random truth values

In this representation True stands for a cell being alive. Now I wrote some code iterating over all cells of the state, counting the True values and so on using a double for loop, but I think there is probably a better numpy solution.

What I'd do in the naive approach:

  1. iterate over all cells of the state (not only the window) (I'd like to formulate some code to to be executed if a cell meets a criteria or another (being alive and surviving or being dead and coming alive))
  2. get the window (wrapping or not wrapping) (function for that I already have)
  3. check if the current cell is alive (could just do a lookup in the state's numpy array)
  4. if it is alive start with an alive neighbors count of -1 otherwise start with 0
  5. count all True values of the window ( np.sum ) and add it to the alive neighbors count (which is -1 if the cell itself was alive, so that I only count neighbors but not the cell itself)
  6. depending on whether the count of alive neighbors is in certain ranges (configurable), write in another (new) state's array True values. (I'd start out with an array, which I created using: np.full((height, width), False, dtype=bool) )
  7. go on with that new array, keeping the old one in a list for history or logging purposes

Basically:

if cell meets criteria:
    write True at the cell's position in a new array

However meeting the criteria depends on multiple rows, because the state's numpy array is a 2D array. That's why I think the linked post is close but not exactly what I need.

How can I do this in an efficient numpy-y way, avoiding unnecessary looping?

Clarification

I am searching for the best way of implementing this in python using numpy and scipy, which aims to be very readable and has good performance.

Perhaps I did not understand all you are trying to do, but what is stopping you from simply using the numpy.sum function?

Example - Let the state be:

import numpy as np
state = np.random.randint(1, 10, (9,9))

Here I am using {0, 1} as values for the state, where 1 means "alive". Then you can just slice around the cell being investigated, eg [2,3]

s = state[1:3,2:5]
if s[1,1]:
   val = -1
else
   val = 0
val += s.sum()

If you put this in a for loop and pay attention to border cases, clamping or wrapping as appropriate, it should do what you describe.

If you are looking for a short elegant implementation, it can be done very efficiently with Python and Numpy .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM