Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I slice a Numpy array up to a boundary?

Tags:

python

numpy

I am using Numpy and Python in a project where a 2D map is represented by an ndarray:

map = [[1,2,3,4,5],
       [2,3,4,2,3],
       [2,2,2,1,2],
       [3,2,1,2,3],
       [4,6,5,7,4]]
MAP_WIDTH = 5, MAP_HEIGHT = 5

An object has a tuple location:

actor.location = (3,3)

and a view range:

actor.range = 2

How do I write the function actor.view_map(map), such that the map returns the area surrounding the actor's location up to a range. For example (using the above map),

range = 1
location = (3, 2)
=>
[[2,3,4],
 [3,4,2],
 [2,2,1]]

but if the actor's range extends too far I want the map filled with -1:

range = 1
location = (1,1)
[[-1,-1,-1],
 [-1, 1, 2],
 [-1, 2, 3]]

the easiest case is a range of 0, which returns the current square:

range = 0
location = (1, 2)
[[2]]

How do I slice my map up to a certain boundary?

like image 728
sdasdadas Avatar asked Apr 07 '13 20:04

sdasdadas


People also ask

Can you slice a NumPy array?

Slice Two-dimensional Numpy ArraysTo slice elements from two-dimensional arrays, you need to specify both a row index and a column index as [row_index, column_index] . For example, you can use the index [1,2] to query the element at the second row, third column in precip_2002_2013 .

Can you add a border of a NumPy array?

Sometimes we need to add a border around a NumPy matrix. Numpy provides a function known as 'numpy. pad()' to construct the border. The below examples show how to construct a border of '0' around the identity matrix.

What is indexing and slicing in NumPy?

Numpy with Python Three types of indexing methods are available − field access, basic slicing and advanced indexing. Basic slicing is an extension of Python's basic concept of slicing to n dimensions. A Python slice object is constructed by giving start, stop, and step parameters to the built-in slice function.

Can you slice arrays in Python?

Array slicing is similar to list slicing in Python. Array indexing also begins from 0 . However, since arrays can be multidimensional, we have to specify the slice for each dimension. As we are mainly working with 2 dimensional arrays in this guide, we need to specify the row and column like what we do in a matrix.


2 Answers

So, thanks to Joe Kington I added a border around my map (filled with -1s).

Here is how I did it but this may not be very Pythonic since I've just started with the language / library:

map = numpy.random.randint(10, size=(2 * World.MAP_WIDTH, 2 * World.MAP_HEIGHT))
map[0 : World.MAP_WIDTH / 4, :] = -1
map[7 * World.MAP_WIDTH / 4 : 2 * World.MAP_WIDTH, :] = -1
map[:, 0 : World.MAP_HEIGHT / 4] = -1
map[:, 7 * World.MAP_HEIGHT / 4 : 2 * World.MAP_WIDTH] = -1
like image 100
sdasdadas Avatar answered Oct 06 '22 00:10

sdasdadas


Here's a little class Box to make using boxes easier --

from __future__ import division
import numpy as np

class Box:
    """ B = Box( 2d numpy array A, radius=2 )
        B.box( j, k ) is a box A[ jk - 2 : jk + 2 ] clipped to the edges of A
        @askewchan, use np.pad (new in numpy 1.7):
            padA = np.pad( A, pad_width, mode="constant", edge=-1 )
            B = Box( padA, radius )
    """

    def __init__( self, A, radius ):
        self.A = np.asanyarray(A)
        self.radius = radius

    def box( self, j, k ):
        """ b.box( j, k ): square around j, k clipped to the edges of A """
        return self.A[ self.box_slice( j, k )]

    def box_slice( self, j, k ):
        """ square, jk-r : jk+r clipped to A.shape """
            # or np.clip ?
        r = self.radius
        return np.s_[ max( j - r, 0 ) : min( j + r + 1, self.A.shape[0] ),
                       max( k - r, 0 ) : min( k + r + 1, self.A.shape[1] )]

#...............................................................................
if __name__ == "__main__":
    A = np.arange(5*7).reshape((5,7))
    print "A:\n", A
    B = Box( A, radius=2 )
    print "B.box( 0, 0 ):\n", B.box( 0, 0 )
    print "B.box( 0, 1 ):\n", B.box( 0, 1 )
    print "B.box( 1, 2 ):\n", B.box( 1, 2 )
like image 37
denis Avatar answered Oct 05 '22 22:10

denis