Reputation: 3299
I have a list with two ndarray of shape (1,3) inside the list. There are 3 similar copy of this inner list.Each of these inner list is further grouped in the outer list which correspond to a an outer-list with len 3.
The idea is to transform the nested list from shape 3 (outer) and 2 (inner) into the shape of shape 2 (outer) and 3 (inner).
The following code is draft
from operator import itemgetter
all_l=[[np.array([[1, 2, 3]]),np.array([[4, 5, 6]])],
[np.array([[1, 2, 3]]),np.array([[4, 5, 6]])],
[np.array([[1, 2, 3]]),np.array([[4, 5, 6]])]]
trans_format=[list ( map ( itemgetter ( i),all_l) ) for i in range (0,len(all_l[0]))]
But, I wonder whether there more efficient way of achieving this? As in actual implementation, the outer and inner len of the list if huge.
Upvotes: 0
Views: 161
Reputation: 9701
You are correct in thinking some efficiency can be gained. Here are some timing comparisons.
It's worth noting that these timings were run on the original dataset, and might show an efficiency shift when scaled up. (Work in progress.)
Answer by @fountainhead:
Time per loop: 10.1 µs
new_arr = np.array(all_l).transpose(1,0,2,3)
Original:
Time per loop: 3.44 µs
trans_format=[list ( map ( itemgetter ( i),all_l) ) for i in range (0,len(all_l[0]))]
Answer by @rapchen:
Time per loop: 1.44 µs
trans_format = [list(row) for row in zip(*all_l)]
This answer (verbose/basic approach):
Time per loop: 1.18 µs
l1 = []
l2 = []
for i in l:
l1.append(i[0])
l2.append(i[1])
trans_format = [l1, l2]
Output for all answers:
(Answer by @foundtainhead outputs a numpy array.)
[[array([[1, 2, 3]]), array([[1, 2, 3]]), array([[1, 2, 3]])],
[array([[4, 5, 6]]), array([[4, 5, 6]]), array([[4, 5, 6]])]]
Upvotes: 1
Reputation: 3722
The following code will give your desired data-structure as a numpy
array:
new_arr = np.array(my_list).transpose(1,0,2,3)
Testing it out:
from pprint import pprint
my_list = [[np.arange(3).reshape(1,3), np.arange(3,6).reshape(1,3)],
[10* np.arange(3).reshape(1,3), 10* np.arange(3,6).reshape(1,3)],
[100*np.arange(3).reshape(1,3), 100*np.arange(3,6).reshape(1,3)]]
pprint (my_list)
new_arr = np.array(my_list).transpose(1,0,2,3)
print (new_arr.shape)
print (new_arr.dtype)
print (new_arr)
Output:
[[array([[0, 1, 2]]), array([[3, 4, 5]])],
[array([[ 0, 10, 20]]), array([[30, 40, 50]])],
[array([[ 0, 100, 200]]), array([[300, 400, 500]])]]
(3, 2, 1, 3)
int32
[[[[ 0 1 2]]
[[ 3 4 5]]]
[[[ 0 10 20]]
[[ 30 40 50]]]
[[[ 0 100 200]]
[[300 400 500]]]]
Converting back to 2x3 list of numpy
arrays:
(Can't imagine why you'd want to do that !)
new_list = [list(slice) for slice in new_arr]
Testing the conversion:
pprint (new_list)
Output of the conversion:
[[array([[0, 1, 2]]), array([[ 0, 10, 20]]), array([[ 0, 100, 200]])],
[array([[3, 4, 5]]), array([[30, 40, 50]]), array([[300, 400, 500]])]]
Upvotes: 1
Reputation: 31
Maybe you can try zip function:
trans_format = list(zip(*all_l))
But then each element of the outer list will be a tuple. If you need inner lists you can simply add a conversion:
trans_format = [list(row) for row in zip(*all_l)]
Upvotes: 0