flatten list of numpy arrays while keeping inner arrays - python

l = [np.array([[1,2],[3,4]]), np.array([5,6]), np.array([[7,8],[9,10],[11,12]])]
I'm trying to flatten this list of arrays but keeping the inner arrays:
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]]
I tried itertools.chain, np.concatenate, np.flatten but none of these options give the output above

Your arrays have different numbers of dimensions, you need to ensure they all are 2D:
out = np.concatenate([x[None,:] if x.ndim == 1 else x for x in l])
output:
array([[ 1, 2],
[ 3, 4],
[ 5, 6],
[ 7, 8],
[ 9, 10],
[11, 12]])
or with itertools.chain with a list output:
from itertools import chain
list(chain.from_iterable([x.tolist()] if x.ndim == 1 else x.tolist()
for x in l))
output: [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]]

You haven't provided your desired output. But, as I understood, you are looking for this:
x = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]]
print([n for m in x for n in m])
with output:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
Please let me know if this is not your desired output.

You basically need to flatten each subarray, concatenate them and finally reshape it.
np.concatenate(list(map(np.ravel, l))).reshape(-1, 2)
output:
array([[ 1, 2],
[ 3, 4],
[ 5, 6],
[ 7, 8],
[ 9, 10],
[11, 12]])

Related

Converting elements of 2D Tensor based on element mapping between old and new values?

I have a 2D tensor that contains the indices into some other tensor.
old = torch.Tensor([
[1, 2, 12, 12],
[0, 1, 12, 12],
[3, 5, 12, 12],
[7, 8, 12, 12],
[6, 7, 12, 12],
[9, 11, 12, 12]])
I have another tensor that represents a mapping between elements in the old tensor to a new tensor
mapping = torch.Tensor([
[0, 0],
[1, 6],
[2, 1],
[3, 6],
[4, 2],
[5, 6],
[6, 3],
[7, 6],
[8, 4],
[9, 6],
[10, 5],
[11, 6],
[12, 6]])
That is, the [:, 0] column of mapping represents the values found in old, and the [:, 1] represents the values to convert the correspond to. Thus the desired output is this new tensor
new_or_desired = torch.Tensor([
[6, 1, 6, 6],
[0, 6, 6, 6],
[6, 6, 6, 6],
[6, 4, 6, 6],
[3, 6, 6, 6],
[6, 6, 6, 6]])
I have tried many iterations but my best idea yet to applying this mapping is
old[old == mapping[:, 0]] = mapping[:, 1]
But the shapes are obviously mis-matched. How can I apply the mapping to convert the old elements to the new elements values? I think I should use scatter_ but I can't quite figure out how to apply it correctly.
This can be achieved with torch.take
new = torch.take(mapping[:, 1], old.long())

How to rotate 90 deg of 2D array inside 3D array?

I have a 3D array consist of 2D arrays, I want to rotate only the 2D arrays inside the 3D array without changing the order, so it will become a 3D array consist of rotated 3D arrays.
For example, I have a 3D array like this.
foo = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
print(foo)
>>> array([[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]])
foo.shape
>>> (2, 2, 3)
I want to rotate it into this.
rotated_foo = np.array([[[4, 1], [5, 2], [6, 3]], [[10, 7], [11, 8], [12, 9]]])
print(rotated_foo)
>>> array([[[ 4, 1],
[ 5, 2],
[ 6, 3]],
[[10, 7],
[11, 8],
[12, 9]]])
rotated_foo.shape
>>> (2, 3, 2)
I've tried it using numpy's rot90 but I got something like this.
rotated_foo = np.rot90(foo)
print(rotated_foo)
>>> array([[[ 4, 5, 6],
[10, 11, 12]],
[[ 1, 2, 3],
[ 7, 8, 9]]])
rotated_foo.shape
>>> (2, 2, 3)
You can use numpy.rot90 by setting axes that you want to rotate.
foo = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
rotated_foo = np.rot90(foo, axes=(2,1))
print(rotated_foo)
Output:
array([[[ 4, 1],
[ 5, 2],
[ 6, 3]],
[[10, 7],
[11, 8],
[12, 9]]])
Try np.transpose and np.flip:
print(np.flip(np.transpose(foo, (0, 2, 1)), axis=2))
Prints:
[[[ 4 1]
[ 5 2]
[ 6 3]]
[[10 7]
[11 8]
[12 9]]]
You want to rotate 90 in the opposite direction of np.rot90, or equivalently rotate by 270 = 3 * 90 in the np.rot90 direction:
>>> np.rot90(foo, k=3, axes=(1, 2))
array([[[ 4, 1],
[ 5, 2],
[ 6, 3]],
[[10, 7],
[11, 8],
[12, 9]]])

Numpy append vectors of same shape to different axis

I have a numpy array
import numpy as np
initial_array = np.array([[
[0, 1],
[1, 2],
[2, 3],
[3, 4]],
[[4, 5],
[5, 6],
[6, 7],
[7, 8]]])
I have an array I want to add in:
to_add = np.array([
[ 8, 9],
[ 9, 10],
[10, 11],
[11, 12]])
Here, initial_array has a shape of (2, 4, 2) and to_add has a shape of (4, 2). I'm looking for the final result with a shape (3, 4, 2):
result = np.array([[
[ 0, 1],
[ 1, 2],
[ 2, 3],
[ 3, 4]],
[[ 4, 5],
[ 5, 6],
[ 6, 7],
[ 7, 8]],
[[ 8, 9],
[ 9, 10],
[10, 11],
[11, 12]]])
How can this be done without converting the numpy array back to a python list, is it possible to do this using numpy alone?
A lot of ways actually, I'm showing a couple:
>>> result = np.insert(initial_array, initial_array.shape[0], to_add, axis=0)
# or
>>> result = np.vstack((initial_array,to_add[None,...]))
# or
>>> result = np.array([*initial_array, to_add])
In addition to the other answers, you can also do that with np.newaxis():
np.concatenate([initial_array, to_add[np.newaxis, :]])
The result:
Out[75]:
array([[[ 0, 1],
[ 1, 2],
[ 2, 3],
[ 3, 4]],
[[ 4, 5],
[ 5, 6],
[ 6, 7],
[ 7, 8]],
[[ 8, 9],
[ 9, 10],
[10, 11],
[11, 12]]])
Without reshape:
np.concatenate((initial_array, [to_add]))
You could just add an additional axis to to_add so they can be directly concatenated:
np.concatenate([initial_array, to_add[None,:]])
array([[[ 0, 1],
[ 1, 2],
[ 2, 3],
[ 3, 4]],
[[ 4, 5],
[ 5, 6],
[ 6, 7],
[ 7, 8]],
[[ 8, 9],
[ 9, 10],
[10, 11],
[11, 12]]])
You can use numpy.append with to_add inside a list and appending only on the axis 0.
initial_array = np.array([[
[0, 1],
[1, 2],
[2, 3],
[3, 4]],
[[4, 5],
[5, 6],
[6, 7],
[7, 8]]])
to_add = np.array([
[ 8, 9],
[ 9, 10],
[10, 11],
[11, 12]])
final = np.append(initial_array, [to_add], axis=0)

Appending to 2 dimensional array in python

I am reading Data from CSV file which comes similar to the below matrix/array
b = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
I would like to change the index of every element greater than 1 to a new row in the arraylist
this will make the above array as below
b = [[1,2],[5,6],[9,10],[3,4],[7,8][11,12]]
what i have done in python (but couldn't get the answer)
b = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
c = b
rows = len(b)
columns = len(b[0])
c[4].append(1)
count = 3
for i in range(rows):
for j in range(columns):
if i > 1:
for k in columns
list1 =
c.insert(count,list1)
count = count + 1
You can use numpy. Perform indexing and concatenate at the end:
import numpy as np
b = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(np.concatenate((b[:,:2], b[:,2:])))
# [[ 1 2]
# [ 5 6]
# [ 9 10]
# [ 3 4]
# [ 7 8]
# [11 12]]
data =[]
data.append(['a',1])
data.append(['b',2])
data.append(['c',3])
data.append(['d',4])
print(data)
output
[['a', 1], ['b', 2], ['c', 3], ['d', 4]]
One line solution np.array(b).reshape(-1,2):
import numpy as np
b = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
np.array(b).reshape(-1,2)
array([[ 1, 2],
[ 3, 4],
[ 5, 6],
[ 7, 8],
[ 9, 10],
[11, 12]])
Why not just split it into two lists, and then recombine them?
new_elements = []
for i in range(len(b)):
if len(b[i]) > 2:
new_elements.append(b[i][2:])
b[i] = b[i][:2]
b.extend(new_elements)
You might want to use numpy arrays and the concatenate function.
import numpy as np
b = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]) # or b = np.array(b)
c = np.concatenate((b[:, :2], b[:, 2:]),0)
If you prefer working with python arrays, you can use list interpretation:
c = [row[:2] for row in b]
c.extend([row[2:] for row in b])
which returns
[[1, 2], [5, 6], [9, 10], [3, 4], [7, 8], [11, 12]]
Using a list comprehension.
Ex:
b = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
n = 2
b = [j[i:i+n] for j in b for i in range(0, len(j), n)]
b = b[0::2] + b[1::2]
print(b)
Output:
[[1, 2], [5, 6], [9, 10], [3, 4], [7, 8], [11, 12]]
Another approach would be this:
b = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
step = 2
length = len(b[0])
b = [elem[i:i+step] for i in range(0,length,step) for elem in b]
print(b)
Output:
[[1, 2], [5, 6], [9, 10], [3, 4], [7, 8], [11, 12]]

permutation of elements inside the list of list

I have a nested list as follows:
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
I need to permute only the elements inside each list.
do you have any idea how can I do this?
You can do something like this:
import random
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for x in A:
random.shuffle(x)
To shuffle each sublist in a list comprehension, you cannot use random.shuffle because it works in place. You can use random.sample with the sample length = the length of the list:
import random
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
new_a = [random.sample(l,len(l)) for l in A]
print(new_a)
an output:
[[2, 1, 3], [5, 4, 6], [7, 9, 8]]
That solution is the best one if you don't want to modify your original list. Else, using shuffle in a loop as someone else answered works fine as well.
Use permutations from itertools:
from itertools import permutations
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
out = []
for i in A:
for j in permutations(i):
out.append(list(j))
print out
OUTPUT:
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1],
[4, 5, 6], [4, 6, 5], [5, 4, 6], [5, 6, 4], [6, 4, 5], [6, 5, 4],
[7, 8, 9], [7, 9, 8], [8, 7, 9], [8, 9, 7], [9, 7, 8], [9, 8, 7]]

Categories

Resources