This question already has answers here:
Merging elements in 2D list based on common first elements
(5 answers)
Closed 1 year ago.
How to combine arrays inside 2D array to a list if the first index value is the same?
Say for example, this 2D array:
[[0 0]
[0 3]
[0 4]
[1 1]
[2 2]
[3 0]
[3 3]
[3 4]
[4 0]
[4 3]
[4 4]]
How will I make it to something like this?
[[0, 0, 3, 4], [1 1], [2 2], [3 0 3 4], [4 0 3 4]]
When converting from numpy to list, I need it to be optimized as there are thousands of rows on my end.
Any suggestion is much appreciated. The end goal is I want the second index value to be combined together.
Also, take into consideration if ever the first index value is not in ascending order.
You can do it like that:
my_list = [
[0, 0],
[0, 3],
[0, 4],
[1, 1],
[2, 2],
[3, 0],
[3, 3],
[3, 4],
[4, 0],
[4, 3],
[4, 4]
]
from collections import defaultdict
d = defaultdict(list)
for i, j in my_list:
d[i].append(j)
combined = [[i]+l for i,l in d.items()]
import numpy as np
import pandas as pd
ll = [[0, 0], [0, 3], [0, 4], [1, 1], [2, 2], [3, 0], [3, 3], [3, 4], [4, 0], [4, 3], [4, 4]]
x = np.array(ll)
df = pd.DataFrame(x)
dx = df.groupby(0).apply(lambda g: g[1].tolist())
[[x[0], *x[1]] for x in zip(dx.index.tolist(), dx.values.tolist())]
I've been looking all over but I'm not really sure how to even describe what it is I want. Essentially I need to turn
np.array(
[[0,0, 1,1, 2,2],
[0,0, 1,1, 2,2],
[3,3, 4,4, 5,5],
[3,3, 4,4, 5,5]]
)
into
np.array(
[[[0,1,2,3,4,5], [0,1,2,3,4,5]],
[[0,1,2,3,4,5], [0,1,2,3,4,5]]
)
I think I can accomplish that using np.reshape and maybe some other stuff but if I try reshape with arguments (2,2,6) I get back
[[[0 0 1 1 2 2]
[0 0 1 1 2 2]]
[[3 3 4 4 5 5]
[3 3 4 4 5 5]]]
which is not quite what I want.
Make your array with a couple of repeats:
In [208]: arr = np.arange(0,6).reshape(2,3)
In [209]: arr
Out[209]:
array([[0, 1, 2],
[3, 4, 5]])
In [210]: arr = arr.repeat(2,0).repeat(2,1)
In [211]: arr
Out[211]:
array([[0, 0, 1, 1, 2, 2],
[0, 0, 1, 1, 2, 2],
[3, 3, 4, 4, 5, 5],
[3, 3, 4, 4, 5, 5]])
Now break it into blocks which we can transpose:
In [215]: arr1 = arr.reshape(2,2,3,2)
In [216]: arr1
Out[216]:
array([[[[0, 0],
[1, 1],
[2, 2]],
[[0, 0],
[1, 1],
[2, 2]]],
[[[3, 3],
[4, 4],
[5, 5]],
[[3, 3],
[4, 4],
[5, 5]]]])
In [217]: arr1.shape
Out[217]: (2, 2, 3, 2)
In [218]: arr1.transpose(1,0,2,3)
Out[218]:
array([[[[0, 0],
[1, 1],
[2, 2]],
[[3, 3],
[4, 4],
[5, 5]]],
[[[0, 0],
[1, 1],
[2, 2]],
[[3, 3],
[4, 4],
[5, 5]]]])
Let's consolidate the middle 2 axes:
In [220]: arr1.transpose(1,0,2,3).reshape(2,6,2)
Out[220]:
array([[[0, 0],
[1, 1],
[2, 2],
[3, 3],
[4, 4],
[5, 5]],
[[0, 0],
[1, 1],
[2, 2],
[3, 3],
[4, 4],
[5, 5]]])
Almost there; just need another transpose:
In [221]: arr1.transpose(1,0,2,3).reshape(2,6,2).transpose(0,2,1)
Out[221]:
array([[[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5]],
[[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5]]])
The basic idea is to reshape the array into blocks, do a transpose, and reshape again. Here I needed another transpose, but if I choose the right one to start with I might not have needed that.
I don't know of a systematic way of doing this; there may be one, but so far I've just used a bit of trial and error when answering this kind of question. Everyone wants a different final arrangement.
This should work:
>>> import numpy as np
>>> A = np.array(
... [[0,0, 1,1, 2,2],
... [0,0, 1,1, 2,2],
... [3,3, 4,4, 5,5],
... [3,3, 4,4, 5,5]]
... )
>>> B = a[::2,::2].flatten()
>>> B
array([0, 1, 2, 3, 4, 5])
>>> C = np.tile(b, (2,2,1))
>>> C
array([[[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5]],
[[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5]]])
We can generalize this for a given n * m matrix, that contain blocks sized n/y * m/x of identical values (so there are y rows and x columns of blocks)
def transform(A, y, x):
dy = A.shape[0]/y
dx = A.shape[1]/x
B = A[::dy, ::dx].flatten()
return np.tile(B, (y,x,1))
I think this is what you are looking for:
import numpy
b=numpy.array([[0,0,1,1,2,2],[0,0,1,1,2,2],[3,3,4,4,5,5],[3,3,4,4,5,5]])
c1=(b[::2,::2].flatten(),b[::2,1::2].flatten())
c2=(b[1::2,::2].flatten(),b[1::2,1::2].flatten())
c=numpy.vstack((c1,c2)).reshape((2,2,6))
print(c)
which outputs:
[[[0 1 2 3 4 5]
[0 1 2 3 4 5]]
[[0 1 2 3 4 5]
[0 1 2 3 4 5]]]
and for general size target array and general size input array this is the algorithm with an example of 3*3 input array:
import numpy
b=numpy.array([[0,0,1,1,2,2],[0,0,1,1,2,2],[0,0,1,1,2,2],[3,3,4,4,5,5],[3,3,4,4,5,5],[3,3,4,4,5,5]])
(m,n)=b.shape
C=b[::int(m/2),::2].flatten(),b[::int(m/2),1::2].flatten()
for i in range(1,int(m/2)):
C=numpy.vstack((C,(b[i::int(m/2),::2].flatten(),b[i::int(m/2),1::2].flatten())))
print(C)
which outputs:
[[0 1 2 3 4 5]
[0 1 2 3 4 5]
[0 1 2 3 4 5]
[0 1 2 3 4 5]
[0 1 2 3 4 5]
[0 1 2 3 4 5]]
I use Pyaudio to record multichannel signal (2 for example) by appending each 2-dimensional list together. Now I would like to find an efficient way to flatten the signal to one single 2 dimensional array:
For example, input is :
i = [[[ 1, 2],
[ 1, 2],
[ 1, 2]],
[[ 3, 4],
[ 3, 4],
[ 3, 4]]
]
i = np.array(i)
this i has a shape of (2,3,2), and I would like to flatten it to shape of (2x3, 2)
array([[1, 2],
[1, 2],
[1, 2],
[3, 4],
[3, 4],
[3, 4]])
Any suggestion? Many thanks
Use np.concatenate:
print(np.concatenate(i, 0))
Output:
[[1 2]
[1 2]
[1 2]
[3 4]
[3 4]
[3 4]]
It should work :
i.reshape(2*3, 2)
Use this -
[item for sublist in i for item in sublist]
[[1, 2], [1, 2], [1, 2], [3, 4], [3, 4], [3, 4]]