Taking the 1st n terms of an array - python

I have an array which looks something like this (will have more than 5 terms but i have only used 5 terms as an example):
states = numpy.array([ [0, 0, 0],
[0, 0, 1],
[0, 2, 0],
[0, 1, 0],
[0, 1, 1]]
I cant seem to find a way to take only the 1st n terms of this array.
For example if n = 3 then:
states = numpy.array([ [0, 0, 0],
[0, 0, 1],
[0, 2, 0],]
I have tried using a loop and list.append but i keep getting the error
"list indices must be integers, not tuple"
since it returns an array which looks like this:
[[array([0, 0, 0])], [array([0, 0, 1])], [array([0, 2, 0])]
There must be a simple way to do this but i have looked for hours and cant find one!
Thank you for your help!!

Your attempt is close, but it isn't working because you are mixing Python's builtin lists with NumPy's arrays. It is important to make this distinction, because they are actually quite different.
Your solution could probably be fixed by using np.vstack instead of list.append, which would return a NumPy array rather than a list.
However, a simpler and preferred method is to use NumPy's slicing:
states[:n]

Related

The dimension orders of the Numpy 3D array are designed to z, x, y. Are there any advantages?

I think that the x,y,z order is more intuitive for a 3D array, just as Matlab does. For example, If someone tells me an array is 2x3x4, I will think it is 2 rows, 3 columns, 4 frames, instead of 2 frames, 3 rows, 4 columns.
Is there any core reason why the creators of NumPy had to do this?
#hpaulj You mentioned that the default input of the Numpy array is the nesting of lists. It inspires me.
For a nesting list,
l=[
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]],
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
]
len(l) # 2
len(l[0]) # 3
len(l[0][0]) # 4
its order of the length keeps consistency with the shape of the Numpy array.
np.array(l).shape # (2, 3, 4)
Maybe that is the reason.

Adding zeros to given positions in a numpy array

I have a numpy array and I want a function that takes as an input the numpy array and a list of indices and returns as an output another array which has the following property: a zero has been added to the initial array just before the position of each of the indices of the origional array.
Let me give a couple of examples:
If indices = [1] and the initial array is array([1, 1, 2]), then the output of the function should be array([1, 0, 1, 2]).
If indices = [0, 1, 3] and the initial array is array([1, 2, 3, 4]), then the output of the function should be array([0, 1, 0, 2, 3, 0, 4]).
I would like to do it in a vectorized manner without any for loops.
Had the same issue before. Found a solution using np.insert:
import numpy as np
np.insert([1, 1, 2], [1], 0)
>>> [1, 0, 1, 2]
I see #jdehesa has commented this already but adding as a permanent answer for future visitors.

subclassing numpy ndarray to simulate padding with zeros on out of bounds indices

I want to have a 2D numpy array (NxN) which will return zeros when an index is either negative or out of bounds (i.e. I want to suppress the usual wrap-around indexing that occurs when an index is -1 or the IndexError when your index is N). I could do this literally, simply adding a border of zeros around the array and treating it as a 1-based array instead of a 0-based array, but this seems inelegant.
I stumbled across a few answers here relating to subclassing the numpy ndarray class and defining your own __getitem__ attribute. My first attempt looked like this:
import numpy as np
class zeroPaddedArray(np.ndarray):
def __getitem__(self, index):
x,y = index
if x < 0 or y < 0 or x >= self.shape[0] or y >= self.shape[1]:
return 0
return super(zeroPaddedArray, self).__getitem__(index)
This sort of works, but only allows you to access array elements as arr[x,y], and throws an error when you try arr[x][y]. It also completely breaks a lot of other functions such as print. print arr gives TypeError: 'int' object is not iterable.
My next attempt was to check if a tuple was given for the index, and to default to the old behavior if not.
import numpy as np
class zeroPaddedArray(np.ndarray):
def __getitem__(self, index):
if type(index) is tuple:
x,y = index
if x < 0 or y < 0 or x >= self.shape[0] or y >= self.shape[1]:
return 0
return super(zeroPaddedArray, self).__getitem__(index)
else:
return super(zeroPaddedArray, self).__getitem__(index)
This gives me the requires zero-padding behavior when indexing as a tuple (arr[-1,-1] correctly gives 0), but allows other functions to work properly. However, now I get different result depending on the way I index things. For example:
a = np.ones((5,5))
b = a.view(zeroPaddedArray)
print b[-1][-1]
print b[-1,-1]
gives
>>>1.0
>>>0
I think this is probably usable as-is for my purposes, but I am unsatisfied. How can I tweak this to give the desired zero-padding behavior regardless of the syntax I use for indexing, without breaking all of the other ndarray functionality?
Here's how take could be used:
In [34]: a=np.zeros((5,5),int)
In [35]: a[1:4,1:4].flat=np.arange(9)
In [36]: a
Out[36]:
array([[0, 0, 0, 0, 0],
[0, 0, 1, 2, 0],
[0, 3, 4, 5, 0],
[0, 6, 7, 8, 0],
[0, 0, 0, 0, 0]])
In [37]: np.take(a, np.arange(-1,6),1,mode="clip")
Out[37]:
array([[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 2, 0, 0],
[0, 0, 3, 4, 5, 0, 0],
[0, 0, 6, 7, 8, 0, 0],
[0, 0, 0, 0, 0, 0, 0]])
In [38]: np.take(a, np.arange(-1,6),0,mode="clip")
Out[38]:
array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 1, 2, 0],
[0, 3, 4, 5, 0],
[0, 6, 7, 8, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]])
I'm using the clip mode to expand the 0 boundary.
There is also an np.pad function, though with all of its generality it is quite long, and no speed solution (it ends up doing 2 concatenates per dimension).
np.lib.index_tricks.py has some good examples of using custom classes to playing indexing tricks.
Before getting too deep into subclassing ndarray I'd suggest writing functions or trick classes to test your ideas.

Numpy slice with array as index

I am trying to extract the full set of indices into an N-dimensional cube, and it seems like np.mgrid is just what I need for that. For example, np.mgrid[0:4,0:4] produces a 4 by 4 matrix containing all the indices into an array of the same shape.
The problem is that I want to do this in an arbitrary number of dimensions, based on the shape of another array. I.e. if I have an array a of arbitrary dimension, I want to do something like idx = np.mgrid[0:a.shape], but that syntax is not allowed.
Is it possible to construct the slice I need for np.mgrid to work? Or is there perhaps some other, elegant way of doing this? The following expression does what I need, but it is rather complicated and probably not very efficient:
np.reshape(np.array(list(np.ndindex(a.shape))),list(a.shape)+[len(a.shape)])
I usually use np.indices:
>>> a = np.arange(2*3).reshape(2,3)
>>> np.mgrid[:2, :3]
array([[[0, 0, 0],
[1, 1, 1]],
[[0, 1, 2],
[0, 1, 2]]])
>>> np.indices(a.shape)
array([[[0, 0, 0],
[1, 1, 1]],
[[0, 1, 2],
[0, 1, 2]]])
>>> a = np.arange(2*3*5).reshape(2,3,5)
>>> (np.mgrid[:2, :3, :5] == np.indices(a.shape)).all()
True
I believe the following does what you're asking:
>>> a = np.random.random((1, 2, 3))
>>> np.mgrid[map(slice, a.shape)]
array([[[[0, 0, 0],
[0, 0, 0]]],
[[[0, 0, 0],
[1, 1, 1]]],
[[[0, 1, 2],
[0, 1, 2]]]])
It produces exactly the same result as np.mgrid[0:1,0:2,0:3]except that it uses a's shape instead of hard-coded dimensions.

Python multi-dimensional array initialization without a loop

Is there a way in Python to initialize a multi-dimensional array / list without using a loop?
Sure there is a way
arr = eval(`[[0]*5]*10`)
or
arr = eval(("[[0]*5]+"*10)[:-1])
but it's horrible and wasteful, so everyone uses loops (usually list comprehensions) or numpy
Depending on your real needs, the de facto "standard" package Numpy might provide you with exactly what you need.
You can for instance create a multi-dimensional array with
numpy.empty((10, 4, 100)) # 3D array
(initialized with arbitrary values) or create the same arrays with zeros everywhere with
numpy.zeros((10, 4, 100))
Numpy is very fast, for array operations.
The following does not use any special library, nor eval:
arr = [[0]*5 for x in range(6)]
and it doesn't create duplicated references:
>>> arr[1][1] = 2
>>> arr
[[0, 0, 0, 0, 0],
[0, 2, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]]
Sure, you can just do
mylist = [
[1,2,3],
[4,5,6],
[7,8,9]
]
I don't believe it's possible.
You can do something like this:
>>> a = [[0] * 5] * 5
to create a 5x5 matrix, but it is repeated objects (which you don't want). For example:
>>> a[1][2] = 1
[[0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0]]
You almost certainly need to use some kind of loop as in:
[[0 for y in range(5)] for x in range(5)]
Recursion is your friend :D
It's a pretty naive implementation but it works!
dim = [2, 2, 2]
def get_array(level, dimension):
if( level != len(dimension) ):
return [get_array(level+1, dimension) for i in range(dimension[level])]
else:
return 0
print get_array(0, dim)
It depends on what you what to initialize the array to, but sure. You can use a list comprehension to create a 5×3 array, for instance:
>>> [[0 for x in range(3)] for y in range(5)]
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> [[3*y+x for x in range(3)] for y in range(5)]
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13, 14]]
Yes, I suppose this still has loops—but it's all done in one line, which I presume is the intended meaning of your question?
a = [[]]
a.append([1,2])
a.append([2,3])
Then
>>> a
[[1, 2], [2, 3]]
If you're doing numerical work using Numpy, something like
x = numpy.zeros ((m,n))
x = numpy.ones ((m,n))
Python does not have arrays. It has other sequence types ranging from lists to dictionaries without forgetting sets - the right one depends on your specific needs.
Assuming your "array" is actually a list, and "initialize" means allocate a list of lists of NxM elements, you can (pseudocode):
for N times: for M times: add an element
for N times: add a row of M elements
write the whole thing out
You say you don't want to loop and that rules out the first two points, but why?
You also say you don't want to write the thing down (in response to JacobM), so how would you exactly do that? I don't know of any other way of getting a data structure without either generating it in smaller pieces (looping) or explicitly writing it down - in any programming language.
Also keep in mind that a initialized but empty list is no better than no list, unless you put data into it. And you don't need to initialize it before putting data...
If this isn't a theoretical exercise, you're probably asking the wrong question. I suggest that you explain what do you need to do with that array.
You can do by this way:
First without using any loop:
[[0] * n] * m
Secondly using simple inline list comprehension:
[[0 for column in range(n)] for row in range(m)]
You can use N-dimensional array (ndarray). Here is the link to the documentation. http://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html

Categories

Resources