Concatenate indices of each Numpy Array in a Matrix - python

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).

Related

Permutation of 2D matrix

I would like to be able to generate all unique permutations of a 2d array in python and keep the order.
Let's say I have a 2D matrix [[1, 2, 3], [4, 5, 6]]. Expected result should be a in 8 x 3 in the form
[[1, 2, 3],
[1, 2, 6],
[1, 5, 3],
[1, 5, 6],
[4, 2, 3],
[4, 2, 6],
[4, 5, 3],
[4, 5, 6]].
Thanks
Transpose the array, and then use itertools.product:
from itertools import product
list(map(list, product(*zip(*data))))
This outputs:
[[1, 2, 3], [1, 2, 6], [1, 5, 3], [1, 5, 6], [4, 2, 3], [4, 2, 6], [4, 5, 3], [4, 5, 6]]
The itertools method with product would be the most readible way to do this, but since your question is tagged numpy, here is how you can do this using only Numpy methods.
1. Permutations without expected order
You can use this method if order is not important for you. This uses np.meshgrid and np.stack with some .reshape to get the permutations you need, minus the order you expect.
import numpy as np
lst = [[1, 2, 3], [4, 5, 6]]
arr = np.array(lst)
np.stack(np.meshgrid(*arr.T),-1).reshape(-1,3)
array([[1, 2, 3],
[1, 2, 6],
[4, 2, 3],
[4, 2, 6],
[1, 5, 3],
[1, 5, 6],
[4, 5, 3],
[4, 5, 6]])
2. Permutations with expected order
Getting the order to work is a bit "hacky" but a small modification over the above array with simple reordering of columns can solve this with pretty much the same code.
import numpy as np
lst = [[1, 2, 3], [4, 5, 6]]
order = [1,0,2]
arr = np.array(lst)[:,order]
np.stack(np.meshgrid(*arr.T),-1).reshape(-1,3)[:,order]
array([[1, 2, 3],
[1, 2, 6],
[1, 5, 3],
[1, 5, 6],
[4, 2, 3],
[4, 2, 6],
[4, 5, 3],
[4, 5, 6]])

Numpy Multidimensional Array

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]])

using numpy broadcast_to create a repeated view of every element in array

I want to repeat every element in an array n times without creating a new location on the memory to reproduce the same output as np.repeat shown below.
using np.broadcast_to i managed to only repeat the whole array n times not every element inside it.
arr = np.array([[1, 2], [3, 4]])
arr
array([[1, 2],
[3, 4]])
np.repeat(arr, 6, axis=0)
array([[1, 2],
[1, 2],
[1, 2],
[1, 2],
[1, 2],
[1, 2],
[3, 4],
[3, 4],
[3, 4],
[3, 4],
[3, 4],
[3, 4]])
In [57]: arr = np.array([[1,2],[3,4]])
In [58]: rarr = np.repeat(arr, 3, axis=0)
In [59]: rarr
Out[59]:
array([[1, 2],
[1, 2],
[1, 2],
[3, 4],
[3, 4],
[3, 4]])
You can't use broadcasting to duplicate this. The underlying raveled memory is different:
In [60]: arr.ravel()
Out[60]: array([1, 2, 3, 4])
In [61]: rarr.ravel()
Out[61]: array([1, 2, 1, 2, 1, 2, 3, 4, 3, 4, 3, 4])
With broadcast_to the regular broadcasting rules apply - new leading dimensions are automatic, and size 1 dimensions are scaled. Thus
In [64]: np.broadcast_to(arr, (3,2,2))
Out[64]:
array([[[1, 2],
[3, 4]],
[[1, 2],
[3, 4]],
[[1, 2],
[3, 4]]])
All values have been 'replicated', but the shape and order is different from your repeat. Any attempt to transpose and reshape elements will result in a copy (with no memory savings).
A different broadcasting produces a layout closer to the repeat:
In [70]: np.broadcast_to(arr[:,None,:], (2,3,2))
Out[70]:
array([[[1, 2],
[1, 2],
[1, 2]],
[[3, 4],
[3, 4],
[3, 4]]])
In [71]: np.broadcast_to(arr[:,None,:], (2,3,2)).reshape(6,2)
Out[71]:
array([[1, 2],
[1, 2],
[1, 2],
[3, 4],
[3, 4],
[3, 4]])
[70] is a view (readonly), but [71] is a copy, with the same memory footprint as rarr.

numpy.concatenate float64(101,1) and float64(101,)

I'm a MatLab user who recently converted to python. I am running a for loop that cuts a longer signal into individual trials, normalizes them to 100% trial and then would like to have the trials listed horizontally in a single variable. My code is
RHipFE=np.empty([101, 1])
newlength = 101
for i in range(0,len(R0X)-1,2):
iHipFE=redataf.RHipFE[R0X[i]:R0X[i+1]]
x=np.arange(0,len(iHipFE),1)
new_x = np.linspace(x.min(), x.max(), newlength)
iHipFEn = interpolate.interp1d(x, iHipFE)(new_x)
RHipFE=np.concatenate((RHipFE,iHipFEn),axis=1)
When I run this, I get the error "ValueError: all the input arrays must have same number of dimensions". Which I assume is because RHipFE is (101,1) while iHipFEn is (101,). Is the best solution to make iHipFEn (101,1)? If so, how does one do this in the above for loop?
Generally it's faster to collect arrays in a list, and use some form of concatenate once. List append is faster than concatenate:
In [51]: alist = []
In [52]: for i in range(3):
...: alist.append(np.arange(i,i+5))
...:
In [53]: alist
Out[53]: [array([0, 1, 2, 3, 4]), array([1, 2, 3, 4, 5]), array([2, 3, 4, 5, 6])]
Various ways of joining
In [54]: np.vstack(alist)
Out[54]:
array([[0, 1, 2, 3, 4],
[1, 2, 3, 4, 5],
[2, 3, 4, 5, 6]])
In [55]: np.column_stack(alist)
Out[55]:
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6]])
In [56]: np.stack(alist, axis=1)
Out[56]:
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6]])
In [57]: np.array(alist)
Out[57]:
array([[0, 1, 2, 3, 4],
[1, 2, 3, 4, 5],
[2, 3, 4, 5, 6]])
Internally, vstack, column_stack, stack expand the dimension of the components, and concatenate on the appropriate axis:
In [58]: np.concatenate([l[:,None] for l in alist],axis=1)
Out[58]:
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6]])

Filling an array with arrays or vectors in python using numpy without a loop

I'm trying to find a way to fill an array with rows of values. It's much easier to express my desired output with an example. Given the input of an N x M matrix, array1,
array1 = np.array([[2, 3, 4],
[4, 8, 3],
[7, 6, 3]])
I would like to output an array of arrays in which each row is an N x N consisting of the values from the respective row. The output would be
[[[2, 3, 4],
[2, 3, 4],
[2, 3, 4]],
[[4, 8, 3],
[4, 8, 3],
[4, 8, 3]],
[[7, 6, 3],
[7, 6, 3],
[7, 6, 3]]]
You can reshape the array from 2d to 3d, then use numpy.repeat() along the desired axis:
np.repeat(array1[:, None, :], 3, axis=1)
#array([[[2, 3, 4],
# [2, 3, 4],
# [2, 3, 4]],
# [[4, 8, 3],
# [4, 8, 3],
# [4, 8, 3]],
# [[7, 6, 3],
# [7, 6, 3],
# [7, 6, 3]]])
Or equivalently you can use numpy.tile:
np.tile(array1[:, None, :], (1,3,1))
Another solution which is sometimes useful is the following
out = np.empty((3,3,3), dtype=array1.dtype)
out[...] = array1[:, None, :]

Categories

Resources