Concatenate 3 unidimensional arrays together in numpy - python

I'm leaving MatLab for numpy and in general it's going ok, but I'm having a nightmare finding a nice pythonic way to do what would have done this in MatLab:
A=[1.0;2.0;3.0;4.0] %Column vector
B=[5.0;6.0;7.0;8.0] %Another one
C=[A,B,B] %4 x 3 matrix
In Python, setting up A like so:
A=np.array([1,2,3,4])
B=np.array([5,6,7,8])
And concatenating like so:
C=np.concatenate((A,B,B),axis=1)
Stacks them one on top of the other, and _C, hstack etc fail as well. I'm guessing I need a nice pyythonic way of turning a (4,) numpy array into a (4,1) array. In my code these vectors are much bigger than this and are created dynamically so I can't just type:
A=np.array([[1],[2],[3],[4]])
Thanks in advance for any help!

I would use dstack
>>> A=np.array([1,2,3,4])
>>> B=np.array([5,6,7,8])
>>> np.dstack((A, B, B))
array([[[1, 5, 5],
[2, 6, 6],
[3, 7, 7],
[4, 8, 8]]])

You can use np.c_[A,B,B], which gives
array([[1, 5, 5],
[2, 6, 6],
[3, 7, 7],
[4, 8, 8]])

>>> C=np.array([A,B,B])
>>> C
array([[1, 2, 3, 4],
[5, 6, 7, 8],
[5, 6, 7, 8]])
or:
>>> C=np.array([A,B,B]).swapaxes(1,0)
>>> C
array([[1, 5, 5],
[2, 6, 6],
[3, 7, 7],
[4, 8, 8]])

Related

Swap/Transpose matrix columns

I have a 2d array like this:
m = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
And I want to swap the first and second columns, which would look like this:
[2, 1, 3]
[5, 4, 6]
[8, 7, 9]
I've looked around, but all I can find is stuff about turning rows into columns. I tried the zip function for example, but again it just does this:
[1, 4, 7]
[2, 5, 8]
[3, 6, 9]
Anyone know how to do this?
I think if you just want the first and second columns swapped you should change the code to be something like this:
for i in m:
i[1],i[0] = i[0],i[1]
for i in m:
i[0],i[1] = i[1],i[0]
output
[[2, 1, 3],
[5, 4, 6],
[8, 7, 9]]

Sum each row of a numpy array with all rows of second numpy array (python)

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.

How to access the nth element of every list inside another list?

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]

NumPy array indexing

I want to extract the second and the 3rd to the fifth columns of the NumPy array, how would I go about it?
A = array([[0, 1, 2, 3, 4, 5, 6], [4, 5, 6, 7, 4, 5, 6]])
A[:, [1, 4:6]]
This obviously doesn't work.
Assuming I've understood you -- it's usually a good idea to explicitly specify the output you want, because it's not obvious -- you could use numpy.r_:
In [27]: A
Out[27]:
array([[0, 1, 2, 3, 4, 5, 6],
[4, 5, 6, 7, 4, 5, 6]])
In [28]: A[:, [1,3,4,5]]
Out[28]:
array([[1, 3, 4, 5],
[5, 7, 4, 5]])
In [29]: A[:, r_[1, 3:6]]
Out[29]:
array([[1, 3, 4, 5],
[5, 7, 4, 5]])
In [37]: A[1:, r_[1, 3:6]]
Out[37]: array([[5, 7, 4, 5]])
which you can then flatten or reshape as you like. r_ is basically a convenience function to generate the right indices, e.g.
In [30]: r_[1, 3:6]
Out[30]: array([1, 3, 4, 5])
Perhaps you are looking for this?
In [10]: A[1:, [1]+range(3,6)]
Out[10]: array([[5, 7, 4, 5]])
Note this gives you the second, fourth, fifth and six columns of all rows but the first.
The second element is A[:,1]. Elements 3-5 (I'm assuming you want inclusive) are A[:,2:5]. You won't be able to extract them with a single call. To get them as an array, you could do
import numpy as np
A = np.array([[0, 1, 2, 3, 4, 5, 6], [4, 5, 6, 7, 4, 5, 6]])
my_cols = np.hstack((A[:,1][...,np.newaxis], A[:,2:5]))
The np.newaxis stuff is just to make A[:,1] a 2D array, consistent with A[:,2:5].
Hope this helps.

Numpy: equivalent of numpy.roll but only for data visualisation

Is there a way to perform a roll on an array, but instead of having a copy of the data having just a different visualisation of it?
An example might clarify: given b a rolled version of a...
>>> a = np.random.randint(0, 10, (3, 3))
>>> a
array([[6, 7, 4],
[5, 4, 8],
[1, 3, 4]])
>>> b = np.roll(a, 1, axis=0)
>>> b
array([[1, 3, 4],
[6, 7, 4],
[5, 4, 8]])
...if I perform an assignment on array b...
>>> b[2,2] = 99
>>> b
array([[ 1, 3, 4],
[ 6, 7, 4],
[ 5, 4, 99]])
...the content of a won't change...
>>> a
array([[6, 7, 4],
[5, 4, 8],
[1, 3, 4]])
...contrarily, I would like to have:
>>> a
array([[6, 7, 4],
[5, 4, 99], # observe as `8` has been changed here too!
[1, 3, 4]])
Thanks in advance for your time and expertise!
This is not possible, sorry. The rolled array cannot be described by a different set of strides, which would be necessary for a NumPy view to work.

Categories

Resources