Related
This question already has answers here:
Transpose list of lists
(14 answers)
Closed last year.
I have a numpy array like this:
array = [[1, 3, 5, 7], [2, 4, 6, 8]]
I would like to concatenate them element-wise. Most of the solutions I have found are able to do this with two separate 2d arrays, but I would like to do this within a single 2d array.
Desired output:
array = [[1, 2], [3, 4], [5, 6], [7, 8]]
Just only line code
array = [[1, 3, 5, 7], [2, 4, 6, 8]]
print(list(zip(*array)))
output :
[(1, 2), (3, 4), (5, 6), (7, 8)]
ljdyer is almost right, but you have only one array, so you can do this:
list(zip(*array))
This is a zip operation. Try:
arr1 = [1, 3, 5, 7]
arr2 = [2, 4, 6, 8]
print(list(zip(arr1,arr2)))
Output:
[(1, 2), (3, 4), (5, 6), (7, 8)]
Or for numpy arrays you have the stack operation:
import numpy as np
a = np.array([1, 3, 5, 7])
b = np.array([2, 4, 6, 8])
c = np.stack((a,b), axis = 1)
print(c)
See https://www.delftstack.com/howto/numpy/python-numpy-zip/
The following code will concatenate array element wise in each column
import numpy as np
array = np.array([[1, 3, 5, 7], [2, 4, 6, 8]])
res = []
for i in range(array.shape[1]):
res.append(array[:, i])
res = np.array(res)
print(res.tolist())
Numpy transpose:
In [382]: np.transpose([[1, 3, 5, 7], [2, 4, 6, 8]])
Out[382]:
array([[1, 2],
[3, 4],
[5, 6],
[7, 8]])
If it already is a numpy array (as opposed to just a list of lists),you can use the T shortcut:
In [383]: arr = np.array([[1, 3, 5, 7], [2, 4, 6, 8]])
In [384]: arr
Out[384]:
array([[1, 3, 5, 7],
[2, 4, 6, 8]])
In [385]: arr.T
Out[385]:
array([[1, 2],
[3, 4],
[5, 6],
[7, 8]])
list-zip is a well known list version of transpose:
In [386]: list(zip(*arr))
Out[386]: [(1, 2), (3, 4), (5, 6), (7, 8)]
Note the result is a list of tuples.
I'm new to numpy, I don't understand how the following works:
np.array([range(i, i + 3) for i in [2, 4, 6]])
and the output is:
array([[2, 3, 4],[4, 5, 6],[6, 7, 8]])
Do you understand list comprehensions? range?
In [12]: [range(i, i + 3) for i in [2, 4, 6]]
Out[12]: [range(2, 5), range(4, 7), range(6, 9)]
np.array converts the range objects to lists, and then builds the array.
In [13]: [list(range(i, i + 3)) for i in [2, 4, 6]]
Out[13]: [[2, 3, 4], [4, 5, 6], [6, 7, 8]]
In [14]: np.array([list(range(i, i + 3)) for i in [2, 4, 6]])
Out[14]:
array([[2, 3, 4],
[4, 5, 6],
[6, 7, 8]])
So basically it's just a variation on the textbook example of making an array from a list of lists:
In [15]: np.array([[1,2,3],[10,11,12]])
Out[15]:
array([[ 1, 2, 3],
[10, 11, 12]])
I have a NumPy array with data [3, 5], and I want to create a function which takes this array, and returns the following (2 x 3 x 2) NumPy array :
[[[3, 3],
[3, 3],
[3, 3]],
[[5, 5],
[5, 5],
[5, 5]]]
However, I have not been able to achieve this, using Numpy's repeat() or tile() functions.
For example:
x = np.array([3, 5])
y = np.repeat(x, [2, 3, 2])
Gives the following error:
ValueError: a.shape[axis] != len(repeats)
And:
x = np.array([3, 5])
y = np.tile(x, [2, 3, 2])
Creates a (2 x 3 x 4) array:
[[[3, 5, 3, 5],
[3, 5, 3, 5],
[3, 5, 3, 5]],
[[3, 5, 3, 5],
[3, 5, 3, 5],
[3, 5, 3, 5]]]
What should my function be?
You could use np. tile, you just miss dividing by the number of elements at repetition axis, in your case it's 1D
x = np.array([3, 5])
y = np.tile(x, [2, 3, 2 // x.shape[0]])
def get_nd(a, shape):
shape = np.array(shape)
a_shape = np.ones_like(shape)
a_shape[-a.ndim:] = a.shape
shape = (shape * 1/a_shape).astype('int')
return np.tile(a, shape)
get_nd(x, (2, 3, 2))
Update
Transpose desired shape, if you are targeting (2, 3, 6), then ask for (6, 3, 2) then transpose the resultant matrix
get_nd(x, (2, 3, 6)).T
Or use the following function instead
def get_nd_rep(a, shape):
shape = np.array(shape)
x_shape = np.ones_like(shape)
x_shape[-a.ndim:] = a.shape
shape = (shape * 1/x_shape).astype('int')
return np.tile(a, shape).T
get_nd_rep(x, (2, 3, 2))
The signature for repeat: np.repeat(a, repeats, axis=None)
It can be used as:
In [345]: np.repeat(x, [2,3])
Out[345]: array([3, 3, 5, 5, 5])
In other words, if the repeats is a list, it should match a in size, saying how many times each element is repeated.
While we could expand the dimensions of x, and try repeats (or tile), a simpler approach is to just expand x, and reshape:
In [349]: np.repeat(x,6)
Out[349]: array([3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5])
In [350]: np.repeat(x,6).reshape(2,3,2)
Out[350]:
array([[[3, 3],
[3, 3],
[3, 3]],
[[5, 5],
[5, 5],
[5, 5]]])
multiple repeats
Another approach is to expand x to 3d, and apply 2 repeats. I had to try several things before I got it right:
In [357]: x[:,None,None]
Out[357]:
array([[[3]],
[[5]]])
In [358]: x[:,None,None].repeat(2,2)
Out[358]:
array([[[3, 3]],
[[5, 5]]])
In [359]: x[:,None,None].repeat(2,2).repeat(3,1)
Out[359]:
array([[[3, 3],
[3, 3],
[3, 3]],
[[5, 5],
[5, 5],
[5, 5]]])
tile
np.tile does something similar (multiple repeats):
In [361]: np.tile(x[:,None,None],(1,3,2))
Out[361]:
array([[[3, 3],
[3, 3],
[3, 3]],
[[5, 5],
[5, 5],
[5, 5]]])
To use repeat or tile I usually need to review the docs and/or try several things. Especially when expanding the dimensions.
broadcasting
The problem is even simpler with broadcasting:
In [370]: res = np.zeros((2,3,2), int)
In [371]: res[:] = x[:,None,None]
In [372]: res
Out[372]:
array([[[3, 3],
[3, 3],
[3, 3]],
[[5, 5],
[5, 5],
[5, 5]]])
though getting the expansion of x dimensions right took a few tries.
from functools import reduce
import numpy as np
import operator as op
DIM = (2, 3, 2) # size of each dimension
CAP = reduce(op.mul, DIM[1:]) # product of DIM
x = np.array([3, 5])
y = np.repeat(x, CAP).reshape(*DIM)
This will generate a 2x3 array of each element of x, repeated.
DIM[0] should be len(x); otherwise, an exception will be raised. This is due to the parameter of np.reshape being incompatible with the shape produced by np.repeat (numpy doc).
This is also the reason why the ValueError was raised in your case.
So I've created a numpy array:
import numpy as np
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
I'm trying to delete the end element of this array's subarray:
a[0] = (a[0])[:-1]
And encounter this issue:
a[0] = (a[0])[:-1]
ValueError: could not broadcast input array from shape (2) into shape (3)
Why can't I change it ?
How do I do it?
Given:
>>> a
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
You can do:
>>> a[:,0:2]
array([[1, 2],
[4, 5],
[7, 8]])
Or:
>>> np.delete(a,2,1)
array([[1, 2],
[4, 5],
[7, 8]])
Then in either case, assign that back to a since the result is a new array.
So:
>>> a=a[:,0:2]
>>> a
array([[1, 2],
[4, 5],
[7, 8]])
If you wanted only to delete 3 in the first row, that is a different problem. You can only do that if you have have an array of python lists since the sublists are not the same length.
Example:
>>> a = np.array([[1,2],[4,5,6],[7,8,9]])
>>> a
array([list([1, 2]), list([4, 5, 6]), list([7, 8, 9])], dtype=object)
If you do that, just stick to Python. You will have lost all the speed and other advantages of Numpy.
If by 'universal' you mean the last element of each row of a N x M array, just use .shape to find the dimensions:
>>> a
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
>>> a.shape
(3, 4)
>>> np.delete(a,a.shape[1]-1,1)
array([[ 1, 2, 3],
[ 5, 6, 7],
[ 9, 10, 11]])
Or,
>>> a[:,0:a.shape[1]-1]
array([[ 1, 2, 3],
[ 5, 6, 7],
[ 9, 10, 11]])
>>> a = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> a
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
>>> type(a)
<class 'numpy.ndarray'>
>>> a.shape
(3, 3)
The variable a is matrix (2D array). It has certain number of rows and columns. In a matrix all the rows must be of same length. As so, in the above example, the matrix cannot be formed if the first row has length 2 and others 3. So deleting the last element of only the first(or any other subset) sub-array is not possible.
Instead you have to delete the last element of all the sub-arrays at the same time.
That can be done as
>>> a[:,0:2]
array([[1, 2],
[4, 5],
[7, 8]])
Or,
>>> np.delete(a,2,1)
array([[1, 2],
[4, 5],
[7, 8]])
This also applies to the elements of other positions. Deleting can be done of any element of the sub-arrays keeping in mind that all the sub-arrays should have same length.
However you can manipulate the last element(or any other) of any sub-array unless the shape remains constant.
>>> a[0][-1] = 19
>>> a
array([[ 1, 2, 19],
[ 4, 5, 6],
[ 7, 8, 9]])
In case you try to form a matrix with rows of unequal length, a 1D array of lists is formed on which no Numpy operations like vector processing, slicing, etc. works (the list operation works)
>>> b = np.array([[1,2,3],[1,2,3]])
>>> c = np.array([[1,2],[1,2,3]])
>>> b
array([[1, 2, 3],
[1, 2, 3]])
>>> b.shape
(2, 3)
>>> c
array([list([1, 2]), list([1, 2, 3])], dtype=object)
>>> c.shape
(2,)
>>> print(type(b),type(c))
<class 'numpy.ndarray'> <class 'numpy.ndarray'>
Both are ndarray, but you can see the second variable c has is a 1D array of lists.
>>> b+b
array([[2, 4, 6],
[2, 4, 6]])
>>> c+c
array([list([1, 2, 1, 2]), list([1, 2, 3, 1, 2, 3])], dtype=object)
Similarly, b+b operation performs the element-wise addition of b with b, but c+c performs the concatenation operation among the two lists.
For Further Ref
How to make a multidimension numpy array with a varying row size?
Here is how:
import numpy as np
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
a = a[:-1]
print(a)
Output:
[[1 2 3]
[4 5 6]]
So I have a Numpy Array with a bunch of numpy arrays inside of them. I want to group them based on the position in their individual array.
For Example:
If Matrix is:
[[1, 2], [2, 3], [4, 5], [6, 7]]
Then the code should return:
[[1, 2, 4, 6], [2, 3, 5, 7]]
This is becuase 1, 2, 4, 6 are all the first elements in their individual arrays, and 2, 3, 5, 7 are the second elements in their individual arrays.
Anyone know some function that could do this. Thanks.
Answer in Python.
Using numpy transpose should do the trick:
a = np.array([[1, 2], [2, 3], [4, 5], [6, 7]])
a_t = a.T
print(a_t)
array([[1, 2, 4, 6],
[2, 3, 5, 7]])
Your data as a list:
In [101]: alist = [[1, 2], [2, 3], [4, 5], [6, 7]]
In [102]: alist
Out[102]: [[1, 2], [2, 3], [4, 5], [6, 7]]
and as a numpy array:
In [103]: arr = np.array(alist)
In [104]: arr
Out[104]:
array([[1, 2],
[2, 3],
[4, 5],
[6, 7]])
A standard idiom for 'transposing' lists is:
In [105]: list(zip(*alist))
Out[105]: [(1, 2, 4, 6), (2, 3, 5, 7)]
with arrays, there's a transpose method:
In [106]: arr.transpose()
Out[106]:
array([[1, 2, 4, 6],
[2, 3, 5, 7]])
The first array is (4,2) shape; its transpose is (2,4).