I want to reshape 2D array into 3D array.I wrote codes,
for i in range(len(array)):
i = np.reshape(i,(2,2,2))
print(i)
i variable has even number's length array like [["100","150","2","4"],["140","120","3","5"]] or
[[“1”,”5”,”6”,”2”],[“4”,”2”,”3”,”7”],[“7”,”5”,”6”,”6”],[“9”,”1”,”8”,”3”],[“3”,”4”,”5”,”6”],[“7”,”8”,”9”,”2”],,[“1”,”5”,”2”,”8”],[“6”,”7”,”2”,”1”],[“9”,”3”,”1”,”2”],[“6”,”8”,”3”,”3”]]
The length is >= 6.
When I run this codes,ValueError: cannot reshape array of size 148 into shape (2,2,2) error happens.
My ideal output is
[[['100', '150'], ['2', '4']], [['140', '120'], ['3', '5']]] or [[[“1”,”5”],[”6”,”2”]],[[“4”,”2”],[”3”,”7”]],[[“7”,”5”],[”6”,”6”]],[[“9”,”1”],[”8”,”3”]],[[“3”,”4”],[”5”,”6”]],[[“7”,”8”],[”9”,”2”]],[[“1”,”5”],[”2”,”8”]],[[“6”,”7”],[”2”,”1”]],[[“9”,”3”],[[”1”,”2”]],[[“6”,”8”],[”3”,”3”]]]
I rewrote the codesy = [[x[:2], x[2:]] for x in i] but output is not my ideal one.What is wrong in my codes?
First of all, you are missing the meaning of reshaping. Let say your origin array has shape (A, B) and you want to reshape it to shape (M, N, O), you have to make sure that A * B = M * N * O. Obviously 148 != 2 * 2 * 2, right?
In your case, you want to reshape an array of shape (N, 4) to an array of shape (N, 2, 2). You can do like below:
x = np.reshape(y, (-1, 2, 2))
Hope this help :)
You don't need to loop to reshape the way you want to, just use arr.reshape((-1,2,2))
In [3]: x = np.random.randint(low=0, high=10, size=(2,4))
In [4]: x
Out[4]:
array([[1, 1, 2, 5],
[8, 8, 0, 5]])
In [5]: x.reshape((-1,2,2))
Out[5]:
array([[[1, 1],
[2, 5]],
[[8, 8],
[0, 5]]])
This approach will work for both of your arrays. The -1 as the first argument means numpy will infer the value of the unknown dimension.
In [76]: arr = np.arange(24).reshape(3,8)
In [77]: for i in range(len(arr)):
...: print(i)
...: i = np.reshape(i, (2,2,2))
...: print(i)
...:
0
....
AttributeError: 'int' object has no attribute 'reshape'
len(arr) is 3, so range(3) produces values, 0,1,2. You can't reshape the number 0.
Or did you mean to reshape arr[0], arr[1], etc?
In [79]: for i in arr:
...: print(i)
...: i = np.reshape(i, (2,2,2))
...: print(i)
...:
[0 1 2 3 4 5 6 7]
[[[0 1]
[2 3]]
[[4 5]
[6 7]]]
[ 8 9 10 11 12 13 14 15]
[[[ 8 9]
[10 11]]
[[12 13]
[14 15]]]
[16 17 18 19 20 21 22 23]
[[[16 17]
[18 19]]
[[20 21]
[22 23]]]
That works - sort of. The prints look ok, but arr itself does not get changed:
In [80]: arr
Out[80]:
array([[ 0, 1, 2, 3, 4, 5, 6, 7],
[ 8, 9, 10, 11, 12, 13, 14, 15],
[16, 17, 18, 19, 20, 21, 22, 23]])
That's because i is the iteration variable. Assigning a new value to it does not change the original object. If that's confusing, you need to review basic Python iteration.
Or we could iterate the range, and use it as an index:
In [81]: for i in range(len(arr)):
...: print(i)
...: x = np.reshape(arr[i], (2,2,2))
...: print(x)
...: arr[i] = x
...:
...:
...:
...:
0
[[[0 1]
[2 3]]
[[4 5]
[6 7]]]
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-81-5f0985cb2277> in <module>()
3 x = np.reshape(arr[i], (2,2,2))
4 print(x)
----> 5 arr[i] = x
6
7
ValueError: could not broadcast input array from shape (2,2,2) into shape (8)
The reshape works, but you can't put a (2,2,2) array back into a slot of shape (8,). The number of elements is right, but the shape isn't.
In other words, you can't reshape an array piecemeal. You have to reshape the whole thing. (If arr was a list of lists, this kind of piecemeal reshaping would work.)
In [82]: np.reshape(arr, (3,2,2,2))
Out[82]:
array([[[[ 0, 1],
[ 2, 3]],
[[ 4, 5],
[ 6, 7]]],
[[[ 8, 9],
[10, 11]],
[[12, 13],
[14, 15]]],
[[[16, 17],
[18, 19]],
[[20, 21],
[22, 23]]]])
Related
I am trying to extract a sub-array using logical indexes as,
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
a
Out[45]:
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[13, 14, 15, 16]])
b = np.array([False, True, False, True])
a[b, b]
Out[49]: array([ 6, 16])
python evaluates the logical indexes in b per element of a. However in matlab you can do something like
>> a = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16]
a =
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
>> b = [2 4]
b =
2 4
>> a(b, b)
ans =
6 8
14 16
how can I achieve the same result in python without doing,
c = a[:, b]
c[b,:]
Out[51]:
array([[ 6, 8],
[14, 16]])
Numpy supports logical indexing, though it is a little different than what you are familiar in MATLAB. To get the results you want you can do the following:
a[b][:,b] # first brackets isolates the rows, second brackets isolate the columns
Out[27]:
array([[ 6, 8],
[14, 16]])
The more "numpy" method will be understood after you will understand what happend in your case.
b = np.array([False, True, False, True]) is similar to b=np.array([1,3]) and will be easier for me to explain. When writing a[[1,3],[1,3]] what happens is that numpy crates a (2,1) shape array, and places a[1,1] in the [0] location and a[3,3] in the second location. To create an output of shape (2,2), the indexing must have the same dimensionality. Therefore, the following will get your result:
a[[[1,1],[3,3]],[[1,3],[1,3]]]
Out[28]:
array([[ 6, 8],
[14, 16]])
Explanation:
The indexing arrays are:
temp_rows = np.array([[1,1],
[3,3]])
temp_cols = np.array([[1,3],
[1,3])
both arrays have dimensions of (2,2) and therefore, numpy will create an output of shape (2,2). Then, it places a[1,1] in location [0,0], a[1,3] in [0,1], a[3,1] in location [1,0] and a[3,3] in location [1,1]. This can be expanded to any shape but for your purposes, you wanted a shape of (2,2)
After figuring this out, you can make things even simpler by utilizing the fact you if you insert a (2,1) array in the 1st dimension and a (1,2) array in the 2nd dimension, numpy will perform the broadcasting, similar to the MATLAB operation. This means that by using:
temp_rows = np.array([[1],[3]])
temp_cols = np.array([1,3])
you can do:
a[[[1],[3]], [1,3])
Out[29]:
array([[ 6, 8],
[14, 16]])
You could use np.ix_ here.
a[np.ix_(b, b)]
# array([[ 6, 8],
# [14, 16]])
Output returned by np.ix_
>>> np.ix_(b, b)
(array([[1],
[3]]),
array([[1, 3]]))
You could make use of a outer product of the b vector. The new dimesion you can obtain from the number of True values using a sum.
import numpy as np
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
b = np.array([False, True, False, True])
#
M = np.outer(b, b)
new_dim = b.sum()
new_shape = (new_dim, new_dim)
selection = a[M].reshape(new_shape)
The result looks like
[[ 6 8]
[14 16]]
I have a list of slices and use them to index a numpy array.
arr = np.arange(25).reshape(5, 5)
# array([[ 0, 1, 2, 3, 4],
# [ 5, 6, 7, 8, 9],
# [10, 11, 12, 13, 14],
# [15, 16, 17, 18, 19],
# [20, 21, 22, 23, 24]])
slice_list = list(map(lambda i: slice(i, i+2), [1, 2]))
# [slice(1, 3, None), slice(2, 4, None)]
print(arr[slice_list])
# == arr[1:3, 2:4]
# [[ 7 8]
# [12 13]]
This works fine but it breaks if I have fewer slices than the number of dimensions
of the array I want to index.
arr3d = arr[np.newaxis, :, :] # dims: [1, 5, 5]
arr3d[:, slice_list]
# IndexError: only integers, slices (`:`), ellipsis (`...`),(`None`)
# numpy.newaxis and integer or boolean arrays are valid indices
The following examples work however:
arr3d[:, slice_list[0], slice_list[1]]
arr3d[[slice(None)] + slice_list]
arr3d[:, [[1], [2]], [2, 3]]
Is there a way I can use a list of slices to index an array with more dimensions.
I want to do things like:
arr[..., slice_list]
arr[..., slice_list, :]
arr[:, slice_list, :]
without thinking about the dimensions of the array and figuring out how many [slice(None)]*X
I have to pad on either side of my slice_list.
You can do that using tuples of slices and ellipsis objects. Just put all the elements to you want to use for indexing into a tuple and use it as index:
import numpy as np
arr = np.arange(24).reshape(2, 3, 4)
print(arr)
# [[[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
#
# [[12 13 14 15]
# [16 17 18 19]
# [20 21 22 23]]]
slice_tup = tuple(map(lambda i: slice(i, i+2), [1, 2]))
print(slice_tup)
# (slice(1, 3, None), slice(2, 4, None))
print(arr[slice_tup])
# [[[20 21 22 23]]]
# arr[..., slice_list]
print(arr[(Ellipsis, *slice_tup)])
# [[[ 6 7]
# [10 11]]
#
# [[18 19]
# [22 23]]]
# arr[..., slice_list, :]
print(arr[(Ellipsis, *slice_tup, slice(None))])
# [[[20 21 22 23]]]
# arr[:, slice_list, :]
print(arr[(slice(None), *slice_tup, slice(None))])
# IndexError: too many indices for array
I have the following multidimensional numpy array:
a = np.arange(16).reshape(2,2,2,2)
I want to assign new different values of the array for each element of certain dimension e.g. 4th dimension
I used the following code:
for i in range(a.shape[3]):
if i == 0:
for t in np.nditer(a[:,:,:,i], op_flags = ['readwrite']):
t[...] = t*2
if i == 1:
for t in np.nditer(a[:,:,:,i], op_flags = ['readwrite']):
t[...] = t*3
print(a)
print(a.shape)
the output is shown as
[[[[ 0 1]
[ 4 3]]
[[ 8 5]
[12 7]]]
[[[16 9]
[20 11]]
[[24 13]
[28 15]]]]
[[[[ 0 3]
[ 4 9]]
[[ 8 15]
[12 21]]]
[[[16 27]
[20 33]]
[[24 39]
[28 45]]]]
(2, 2, 2, 2)
(2, 2, 2, 2)
What I understand that it iterates over the array and at the first i it assigns new values then at the next i it assigns new values and creates new array with both new values besides the first array of the first i that's why I got two arrays in one variable. I only concern about the last array where all values have been assigned the new values. How could I extract the last array only. Or there is another code which is simpler and time saving for this task?
You can simply do this:
>>> a[:,:,:,0] = a[:,:,:,0]*2
>>> a[:,:,:,1] = a[:,:,:,1]*3
>>> a
array([[[[ 0, 3],
[ 4, 9]],
[[ 8, 15],
[12, 21]]],
[[[16, 27],
[20, 33]],
[[24, 39],
[28, 45]]]])
Or even this:
>>> a[:,:,:,0] *= 2
>>> a[:,:,:,1] *= 3
I have a NumPy array of shape (2,76020,2). Basically it is made of two columns containing 76020 rows each, and each row has two entries.
I want to multiply each column by a different weight, say column 1 by 3 and column 2 by 5. For example:
m =
[3,4][5,8]
[1,2][2,2]
a = [3,5]
I want:
[9,12][25,40]
[3,6][10,10]
I thought I could just multiply m*a, but that gives me instead:
[9,20][15,40]
[3,10][6,10]
How can I write this multiplication?
It's a problem of broadcasting: you must align the dimensions to multiply, here the second:
m = array(
[[[3,4],[5,8]],
[[1,2],[2,2]]])
a = array([3,5])
print(a[None,:,None].shape, m*a[None,:,None])
"""
(1, 2, 1)
[[[ 9 12]
[25 40]]
[[ 3 6]
[10 10]]]
"""
As #B.M. says, this is a 'array broadcasting' issue. (The idea behind his answer is correct, but I think his and the OP's dimensions aren't matching up correctly.)
>>> m = np.array([[[3,4],[5,8]],[[1,2],[2,2]]])
>>> print(m)
[[[3 4]
[5 8]]
[[1 2]
[2 2]]]
>>> print(m.shape)
(2, 2, 2)
>>> a = np.array([3,5])
>>> print(a.shape)
(2,)
We need the shapes of m and a to match, so we have to 'broadcast' a to the correct shape:
>>> print(a[:, np.newaxis, np.newaxis].shape)
(2, 1, 1)
>>> b = a[:, np.newaxis, np.newaxis] * m
>>> print(b)
[[[ 9 12]
[15 24]]
[[ 5 10]
[10 10]]]
In this way the first dimension of a is preserved, and maps to each element of the first dimension of m. But there are also two new dimensions ('axes') created to 'broadcast' into the other two dimensions of m.
Note: np.newaxis is (literally) None, they have the same effect. The former is more readable to understand what's happening. Additionally, just in terms of standard terminology, the first dimension (axis) is generally referred to as the 'rows', and the second axis the 'columns'.
Your description is ambiguous
Basically it is made of two columns containing 76020 rows each, and each row has two entries.
In (2,76020,2), which 2 is columns, and which is entries?
I believe your m is (that display is also ambiguous)
In [8]: m
Out[8]:
array([[[3, 4],
[5, 8]],
[[1, 2],
[2, 2]]])
In [9]: m*a
Out[9]:
array([[[ 9, 20],
[15, 40]],
[[ 3, 10],
[ 6, 10]]])
That's the same as m*a[None,None,:]. When broadcasting, numpy automatically adds dimensions at the beginning as needed. Or iteratively:
In [6]: m[:,:,0]*3
Out[6]:
array([[ 9, 15],
[ 3, 6]])
In [7]: m[:,:,1]*5
Out[7]:
array([[20, 40],
[10, 10]])
Since m is (2,2,2) shape, we can't off hand tell which axis a is supposed to multiply.
According to the accepted answer, you want to multiply along the middle axis
In [16]: m*a[None,:,None]
Out[16]:
array([[[ 9, 12],
[25, 40]],
[[ 3, 6],
[10, 10]]])
But what if m was (2,3,2) in shape? a would then have to have 3 values
In [17]: m=np.array([[[3,4],[5,8],[0,0]],[[1,2],[2,2],[1,1]]])
In [18]: m*a[None,:,None]
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-18-f631c33646b7> in <module>()
----> 1 m*a[None,:,None]
ValueError: operands could not be broadcast together with shapes (2,3,2) (1,2,1)
The alternative broadcastings work
In [19]: m*a[:,None,None]
Out[19]:
array([[[ 9, 12],
[15, 24],
[ 0, 0]],
[[ 5, 10],
[10, 10],
[ 5, 5]]])
In [20]: m*a[None,None,:]
Out[20]:
array([[[ 9, 20],
[15, 40],
[ 0, 0]],
[[ 3, 10],
[ 6, 10],
[ 3, 5]]])
Now if m had distinct dimensions, e.g. (3,1000,2), we could tell at a glance with axis a 2 element weight array would work with.
This seems like a really simple question but I can't find a good answer anywhere. How might I multiply (in place) select columns (perhaps selected by a list) by a scalar using numpy?
E.g. Multiply columns 0 and 2 by 4
In: arr=([(1,2,3,5,6,7), (4,5,6,2,5,3), (7,8,9,2,5,9)])
Out: arr=([(4,2,12,5,6,7), (16,5,24,2,5,3), (28,8,36,2,5,9)])
Currently I am doing this in multiple steps but I feel like there must be a better way especially if the list gets larger. Current way:
arr['f0'] *= 4
arr['f2'] *= 4
You can use array slicing as follows for this -
In [10]: arr=([(1,2,3,5,6,7), (4,5,6,2,5,3), (7,8,9,2,5,9)])
In [11]: narr = np.array(arr)
In [13]: narr[:,(0,2)] = narr[:,(0,2)]*4
In [14]: narr
Out[14]:
array([[ 4, 2, 12, 5, 6, 7],
[16, 5, 24, 2, 5, 3],
[28, 8, 36, 2, 5, 9]])
An alternate solution is to create a class that inherits from np.ndarray and add a method to it to make the in-place mutation more intuitive.
Code:
import numpy as np
class A(np.ndarray):
def __new__(cls, a):
arr = np.asarray(a)
arr = arr.view(cls)
return arr
def mutate(self, col, k):
self[:,col] *= k
return self
a = A([(1,2,3,5,6,7), (4,5,6,2,5,3), (7,8,9,2,5,9)])
print a
print '---------------------'
a.mutate(0, 4)
a.mutate(2, 4)
print a
Result:
[[1 2 3 5 6 7]
[4 5 6 2 5 3]
[7 8 9 2 5 9]]
---------------------
[[ 4 2 12 5 6 7]
[16 5 24 2 5 3]
[28 8 36 2 5 9]]
You can use the following along with array slicing
arr=([(1,2,3,5,6,7), (4,5,6,2,5,3), (7,8,9,2,5,9)])
array = np.array(arr)
array[:,(0,2)]*=4
array
Out[10]:
array([[ 4, 2, 12, 5, 6, 7],
[16, 5, 24, 2, 5, 3],
[28, 8, 36, 2, 5, 9]])