Suppose I create a 2 dimensional array
m = np.random.normal(0, 1, size=(1000, 2))
q = np.zeros(shape=(1000,1))
print m[:,0] -q
When I take m[:,0].shape I get (1000,) as opposed to (1000,1) which is what I want. How do I coerce m[:,0] to a (1000,1) array?
By selecting the 0th column in particular, as you've noticed, you reduce the dimensionality:
>>> m = np.random.normal(0, 1, size=(5, 2))
>>> m[:,0].shape
(5,)
You have a lot of options to get a 5x1 object back out. You can index using a list, rather than an integer:
>>> m[:, [0]].shape
(5, 1)
You can ask for "all the columns up to but not including 1":
>>> m[:,:1].shape
(5, 1)
Or you can use None (or np.newaxis), which is a general trick to extend the dimensions:
>>> m[:,0,None].shape
(5, 1)
>>> m[:,0][:,None].shape
(5, 1)
>>> m[:,0, None, None].shape
(5, 1, 1)
Finally, you can reshape:
>>> m[:,0].reshape(5,1).shape
(5, 1)
but I'd use one of the other methods for a case like this.
Related
I have an numpy array of shape (2000,1) and I need the shape to be (2000,7).
The values in the 6 column we are adding can be anything.
Is there a function or method to accomplish this?
Thanks.
You can try numpy.hstack for this.
>>> x = np.zeros((2000, 1))
>>> x.shape
(2000, 1)
>>> x = np.hstack((x, np.zeros((2000, 6))))
>>> x.shape
(2000, 7)
An interesting option is np.pad function.
The second parameter (pad_with - a list of 2-tuples) defines how many
elements to add at the beginning / end of each dimension.
Example:
arr = np.arange(1,7)[:, np.newaxis]
arr.shape # (6, 1)
result = np.pad(arr, [(0, 0), (0, 6)])
result.shape # (6, 7)
There can be passed also third parameter - mode - defining various
ways what value to pad with. For details see the documentation.
You can do this with broadcasting:
x = np.zeros((2000, 1))
np.broadcast_to(x, (2000,7))
In this case, the values in the first row will be repeated along the second axis.
The question is on how to join two arrays in this case more efficiently- There's a numpy array one of shape (N, M, 1) and array two of shape (M,F). It's required to join the second array with the first, to create an array of the shape (N, M, F+1). The elements of the second array will be broadcast along N.
One solution is copying array 2 to have size of the first (along all dims but one) and then concatenate. But this if the copying can be done as a broadcast during the join/concat it would use much lesser memory.
Any suggestions on how to make this more efficient?
The setup:
import numpy as np
arr1 = np.random.randint(0,10,(5,10))
arr1 = np.expand_dims(arr1, axis=-1) #(5,10, 1)
arr2 = np.random.randint(0,4,(10,15))
arr2 = np.expand_dims(arr2, axis=0) #(1, 10, 15)
arr2_2 = arr2
for i in range(len(arr1)-1):
arr2_2 = np.concatenate([arr2_2, arr2],axis=0)
arr2_2.shape #(5, 10, 15)
np.concatenate([arr1, arr2_2],axis=-1) # (5, 10, 16) -> correct end result
Joining arr1 and arr2 to get
try this
>>> a = np.random.randint(0, 10, (5, 10))
>>> b = np.random.randint(0, 4, (10, 15))
>>> c = np.dstack((a[:, :, np.newaxis], np.broadcast_to(b, (a.shape[0], *b.shape))))
>>> a.shape, b.shape, c.shape
((5, 10), (10, 15), (5, 10, 16)))
I want to change a value of given array in numpy to a multiplication of other elements of the array. Therefore I want to extract the multi_index and manipulate it so that I can identify the position and use it. (e.g. nditer through all elements and always do 'current position in array = next position +position above in array'
I tried to call a function with the multi_index of the current position and want said function to take it and e.g. increase it by one position. (<0 , 1> ---> <0 , 2> while <0 , n> n>=length otherwise <0 , 1> ---> <1 , 0>)
import numpy as np;
def fill(multi_index):
"This will get the new value of the current iteration value judgeing from its index"
return a[(multi_index + <0,1>) + (multi_index + <0,-1>) + (multi_index + <1,0>) + (multi_index + <-1,0>)]
#a = np.random.uniform(0, 100, size=(100, 100))
a = np.arange(6).reshape(2,3)
it = np.nditer(a, flags=['multi_index'], op_flags=['readwrite'])
while not it.finished:
it[0] = fill(it.multi_index)
print(it[0])
it.iternext()
"""for x in np.nditer(a, flags=['multi_index'], op_flags=['readwrite']):
print(x)"""
I don't understand how to extract the actual "coordinates" from the multi_index. I am kinda new to python so please try to explain it thoroughly if possible. Thanks.
Edit: Before I only coded on C++ and a bit Java, so I used to mainly using arrays (in c++ it would be somthing like this:
int main() {
int a[100][100];
for (int i=1, i<=a.length-1, i++) {
for (int j=1, i<=a.width-1, j++) {
a[i][j] = 1/4 (a[i][j+1]+a[i][j-1]+a[i+1][j]+a[i-1][j]);
}
}
return 0;
}
In [152]: a = np.arange(6).reshape(2,3)
In [153]: a
Out[153]:
array([[0, 1, 2],
[3, 4, 5]])
Let's run your nditer and look at its values:
In [157]: it = np.nditer(a, flags=['multi_index'], op_flags=['readwrite'])
In [158]: while not it.finished:
...: print(it.multi_index, a[it.multi_index], it[0], type(it[0]))
...: it.iternext()
...:
(0, 0) 0 0 <class 'numpy.ndarray'>
(0, 1) 1 1 <class 'numpy.ndarray'>
(0, 2) 2 2 <class 'numpy.ndarray'>
(1, 0) 3 3 <class 'numpy.ndarray'>
(1, 1) 4 4 <class 'numpy.ndarray'>
(1, 2) 5 5 <class 'numpy.ndarray'>
At each iteration multiindex is a tuple of the i,j indices. a[it.multiindex] then selects that item from the array. But it[0] is also that item, but wrapped as a 0d array. If you aren't comfortable with the idea of a 0d array (shape ()) then nditer is not the tool for you (at this time).
If you just want the sequential indexing tuples, ndindex works just as well:
In [162]: list(np.ndindex(a.shape))
Out[162]: [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]
(in fact, np.lib.index_tricks.py shows that ndindex uses the nditer multiindex. nditer isn't commonly used in numpy Python level code.)
Or to get indices plus value:
In [177]: list(np.ndenumerate(a))
Out[177]: [((0, 0), 0), ((0, 1), 1), ((0, 2), 2), ((1, 0), 3), ((1, 1), 4), ((1, 2), 5)]
Just values in flat order:
In [178]: a.ravel()
Out[178]: array([0, 1, 2, 3, 4, 5])
BUT, in numpy we prefer not to iterate at all. Instead we try to write code that works with the whole array, using the fast compiled numpy methods. Iteration on arrays is slow, slower than iteration on lists.
===
Looks like your iteration, in a somewhat stylized sense, is:
for i in range(n):
for j in range(m):
a[i,j] = ( a[i,j+1] + a[i,j-1] + a[i+1,j] + a[i-1,j] )/4
There some details to worry about. What about the edges, where j+/-1 is out of bounds? And is this calculation sequential, so that a[i,j] depends on the changes just made to a[i,j-1]; or is it buffered?
In general sequential, iterative calculations on an array like this are a bad fit for numpy.
On the other hand, buffered calculations can be nicely done with whole-array slices
x[1:-1, 1:-1] = (x[:,:-1]+x[:,1:]+x[:-1,:]+x[1:,:])/4
There are also, in scipy some convolution functions that perform calculations on moving windows.
import numpy as np
image1 = np.zeros((120, 120))
image2 = np.zeros((120, 120))
image3 = np.zeros((120, 120))
pack1 = np.array([image1,image2,image3])
pack2 = np.array([image1,image2,image3])
result = np.array([pack1,pack2])
print result.shape
the result is :
(2, 3, 120, 120)
Question : how can I make array with shape (2,120,120,3) with same data without mixing?
Use np.rollaxis to move (OK, roll) a single axis to a specified position:
>>> a.shape
(2, 3, 11, 11)
>>> np.rollaxis(a, 0, 4).shape
(3, 11, 11, 2)
Here the syntax is "roll the zeroth axis so that it becomes the 4th in the new array".
Notice that rollaxis creates a view and does not copy:
>>> np.rollaxis(a, 0, 4).base is a
True
An alternative (and often more readable) way would be to use the fact that np.transpose accepts a tuple of where to place the axes. Observe:
>>> np.transpose(a, (1, 2, 3, 0)).shape
(3, 11, 11, 2)
>>> np.transpose(a, (1, 2, 3, 0)).base is a
True
Here the syntax is "permute the axes so that what was the zeroth axis in the original array becomes the 4th axis in the new array"
You can transpose your packs
pack1 = np.array([image1,image2,image3]).T
pack2 = np.array([image1,image2,image3]).T
and the result has your desired shape.
The (relatively) new stack function gives more control that np.array on how arrays are joined.
Use stack to join them on a new last axis:
In [24]: pack1=np.stack((image1,image2,image3),axis=2)
In [25]: pack1.shape
Out[25]: (120, 120, 3)
In [26]: pack2=np.stack((image1,image2,image3),axis=2)
then join on a new first axis (same as np.array()):
In [27]: result=np.stack((pack1,pack2),axis=0)
In [28]: result.shape
Out[28]: (2, 120, 120, 3)
Say I have matrix X with X.ndim = n. I now want to create a new matrix that has n "singleton" dimensions.
For example, when n=2, and I create a new range, I want to create it like
>>> bar = np.arange(0, 5)[np.newaxis, np.newaxis, ...]
>>> bar.shape
(1, 1, 5)
such that it has 2 singleton dimensions. Say n = 5. How would I generically generate my bar such that it has shape (1,1,1,1,1,5)?
One way could be to create the new array specifying the ndmin parameter:
>>> np.array(np.arange(5), ndmin=6).shape
(1, 1, 1, 1, 1, 5)
NumPy adds the new dimensions on the left.
Alternatively you could use reshape and pass in a tuple specifying the required shape:
>>> np.arange(5).reshape((1,)*5 + (5,)).shape
(1, 1, 1, 1, 1, 5)
>>> n=5
>>> bar = np.arange(0, 5)[(np.newaxis, )*n]
>>> bar.shape
(1, 1, 1, 1, 1, 5)