This question already has answers here:
numpy array concatenate: "ValueError: all the input arrays must have same number of dimensions"
(4 answers)
Closed 2 years ago.
My use case is causing me to struggle with numpy append and concatenate. I wanted to reach out to determine if there is a clean way of handling the following challenge.
I have two numpy arrays:
a = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
b = [10, 11, 12]
I would like to combine so that they look like this:
c = [[1, 2, 3, 10],
[4, 5, 6, 11],
[7, 8, 9, 12]]
Any help would be appreciated.
The most convenient way is np.c_ which handles 1D arrays intelligently:
a = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
b = [10, 11, 12]
np.c_[a,b]
# array([[ 1, 2, 3, 10],
# [ 4, 5, 6, 11],
# [ 7, 8, 9, 12]])
In vanilla python you can do a list comprehension with zip:
out = [u+[v] for u,v in zip(a,b)]
# [[1, 2, 3, 10], [4, 5, 6, 11], [7, 8, 9, 12]]
But since you tagged numpy, you can use hstack like this:
np.hstack((a,np.array([b]).T))
array([[ 1, 2, 3, 10],
[ 4, 5, 6, 11],
[ 7, 8, 9, 12]])
You should try this :
a = [[1,2,3],[4,5,6],[7,8,9]]
b = [10,11,12]
for k in range(len(a)):
a[k].append(b[k])
I'm not entirely sure this would work in any case but it works for that example at least. This doesn't use Numpy though, it works on Python list as well.
In addition to other answers, since you mentioned numpy and concatenate,
here is the way to do it using them:
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
b = np.array([10, 11, 12])
print(np.concatenate((a, b.reshape((-1, 1))), axis=1))
[[ 1 2 3 10]
[ 4 5 6 11]
[ 7 8 9 12]]
Related
Lets say we have a numpy array:
A = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]])
Can anyone explain why this line is used to swap two rows(in this occasion the 1st with the 4th)?
'A[[0, 3]] = A [[3, 0]]'
You are updating the positions of two subarrays simultaneously.
However, doing:
A[0] = A[3]
A[3] = A[0]
would not work because the subarray A[0] has already been updated, so you need to do it simultaneously with:
A[[0, 3]] = A [[3, 0]]
A
array([[10, 11, 12],
[ 4, 5, 6],
[ 7, 8, 9],
[ 1, 2, 3]])
my_function must expand a 1D numpy array to a 2D numpy array, with the 2nd axis containing the slices of length starting from the first index until the end. Example:
import numpy as np
a = np.arange(10)
print (my_function(a, length=3))
Expected output
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6],
[5, 6, 7],
[6, 7, 8],
[7, 8, 9]])
I can achieve this using a for loop, but I was wondering if there is a numpy vectorization technique for this.
def my_function(a, length):
b = np.zeros((len(a)-(length-1), length))
for i in range(len(b)):
b[i] = a[i:i+length]
return b
If you're careful with the math and heed the warningin the docs, you can use np.lib.stride_tricks.as_strided(). You need to calculate the correct dimensions for your array so you don't overflow. Also note that as_strided() shares memory, so you will multiple references to the same memory in the final output. (You can of course, copy this to a new array).
>> import numpy as np
>> def my_function(a, length):
stride = a.strides[0]
l = len(a) - length + 1
return np.lib.stride_tricks.as_strided(a, (l, length), (stride,stride) )
>> np.array(my_function(np.arange(10), 3))
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6],
[5, 6, 7],
[6, 7, 8],
[7, 8, 9]])
>> np.array(my_function(np.arange(15), 7))
array([[ 0, 1, 2, 3, 4, 5, 6],
[ 1, 2, 3, 4, 5, 6, 7],
[ 2, 3, 4, 5, 6, 7, 8],
[ 3, 4, 5, 6, 7, 8, 9],
[ 4, 5, 6, 7, 8, 9, 10],
[ 5, 6, 7, 8, 9, 10, 11],
[ 6, 7, 8, 9, 10, 11, 12],
[ 7, 8, 9, 10, 11, 12, 13],
[ 8, 9, 10, 11, 12, 13, 14]])
How about this function?
import numpy as np
def my_function(a, length):
result = []
for i in range(length):
result.append(a + i)
return np.vstack(result).T[:len(a) - length + 1]
a = np.arange(10)
length = 3
my_function(a, length)
I would like to know if there is any fast way to sum each row of a first array with all rows of a second array. In this case both arrays have the same number of colulmns. For instance if array1.shape = (n,c) and array2.shape = (m,c), the resulting array would be an array3.shape = ((n*m), c)
Look at the example below:
array1 = np.array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
array2 = np.array([[0, 1, 2],
[3, 4, 5]])
The result would be:
array3 = np.array([[0, 2, 4],
[3, 5, 7]
[3, 5, 7]
[6, 8, 10]
[6, 8, 10]
[9, 11, 13]])
The only way I see I can do this is to repeat each row of one of the arrays the number of rows of the other array. For instance, by doing np.repeat(array1, len(array2), axis=0) and then sum this array with array2. This is not very practical however if the number of rows is too big. The other way would be with a for loop but this is too slow.
Any other better way to do it..?
Thanks in advance.
Extend array1 to 3D so that it becomes broadcastable against 2D array2 and then perform broadcasted addition and a final reshape is needed for desired output -
In [30]: (array1[:,None,:] + array2).reshape(-1,array1.shape[1])
Out[30]:
array([[ 0, 2, 4],
[ 3, 5, 7],
[ 3, 5, 7],
[ 6, 8, 10],
[ 6, 8, 10],
[ 9, 11, 13]])
You could try the following inline code if you haven't already. This is the simplest and probably also the quickest on a single thread.
>>> import numpy as np
>>> array1 = np.array([[0, 1, 2],
... [3, 4, 5],
... [6, 7, 8]])
>>>
>>> array2 = np.array([[0, 1, 2],
... [3, 4, 5]])
>>> array3 = np.array([i+j for i in array1 for j in array2])
>>> array3
array([[ 0, 2, 4],
[ 3, 5, 7],
[ 3, 5, 7],
[ 6, 8, 10],
[ 6, 8, 10],
[ 9, 11, 13]])
>>>
If you are looking for speed up by treading, you could consider using CUDA or multithreading. This suggestion goes a bit out of scope of your question but gives you an idea of what can be done to speed up matrix operations.
let's say I have this:
(numpy array)
a=
[0 1 2 3],
[4 5 6 7],
[8 9 10 11]
to get [1,1] which is 5 its diagonal is zero; according to numpy, a.diagonal(0)= [0,5,10]. How do I get the reverse or the right to left diagonal [2,5,8] for [1,1]? Is this possible?
My original problem is an 8 by 8 (0:7).. I hope that helps
Get a new array each row reversed.
>>> import numpy as np
>>> a = np.array([
... [0, 1, 2, 3],
... [4, 5, 6, 7],
... [8, 9, 10, 11]
... ])
>>> a[:, ::-1]
array([[ 3, 2, 1, 0],
[ 7, 6, 5, 4],
[11, 10, 9, 8]])
>>> a[:, ::-1].diagonal(1)
array([2, 5, 8])
or using numpy.fliplr:
>>> np.fliplr(a).diagonal(1)
array([2, 5, 8])
Flip the array upside-down and use the same:
np.flipud(a).diagonal(0)[::-1]
Another way to achieve this is to use np.rot90
import numpy as np
a = np.array([[0, 1, 2, 3],
[4, 5, 6, 7],
[8, 9, 10, 11]])
my_diag = np.rot90(a).diagonal(-1)
Result:
>>> my_diag
array([2, 5, 8])
A number of answers so far. #Akavall is closest as you need to rotate or filip and transpose (equivilant operations). I haven't seen a response from the OP regarding expected behavior on the "long" part of the rectangle.
Generalized solution for a square matrix:
a = 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]])
>>> [(i, np.rot90(a).diagonal(2*i-a.shape[0]+1)) for i in range(a.shape[0])]
[(0, array([0])),
(1, array([ 2, 6, 10])),
(2, array([ 4, 8, 12, 16, 20])),
(3, array([14, 18, 22])),
(4, array([24]))]
As a function:
def reverse_diag(arr, n):
idx = 2*n - arr.shape[0]+1
return np.rot90(arr).diagonal(idx)
original matrix can be made square with a[:np.min(a.shape),:np.min(a.shape)]
EDIT: OP indicated the array is square.... Final Answer is the above
This must be a very basic question, so please bear with me. I have a list of lists like this
l = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
I want to access the second value in each list within the outer list as another list
[2, 5, 8, 11]
Is there a one-step way of doing this? Having programmed in Matlab quite a lot before, I tried l[:][1] but that returns me [4, 5, 6]
Use a list comprehension:
>>> lis = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
>>> [ x[1] for x in lis]
[2, 5, 8, 11]
Another way using operator.itemgetter:
>>> from operator import itemgetter
>>> map( itemgetter(1), lis)
[2, 5, 8, 11]
Since you mention Matlab, I'm going to mention the numpy way of doing this. That may actually be closer to what you'd like, and if you're going to use Matlab like things a lot, it's better to start using numpy early:
import numpy
a = numpy.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
>>> a[:,1]
array([ 2, 5, 8, 11])
So yes, there is a conversion step to numpy arrays extra, but possibly you want to continue on with an array, instead of using a list, as it offers lots of extras.
>>> L = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
>>> [item[1] for item in L]
[2, 5, 8, 11]