Transpose Nested List in Python

Transpose nested list in python

Use zip with * and map:

>>> map(list, zip(*a))
[['AAA', 'BBB', 'CCC', 'DDD', 'EEE', 'FFF', 'GGG', 'HHH', 'III'],
['1', '262', '86', '48', '8', '39', '170', '16', '4'],
['1', '56', '84', '362', '33', '82', '296', '40', '3'],
['10', '238', '149', '205', '96', '89', '223', '65', '5'],
['92', '142', '30', '237', '336', '140', '210', '50', '2']]

Note that map returns a map object in Python 3, so there you would need list(map(list, zip(*a)))

Using a list comprehension with zip(*...), this would work as is in both Python 2 and 3.

[list(x) for x in zip(*a)]

NumPy way:

>>> import numpy as np
>>> np.array(a).T.tolist()
[['AAA', 'BBB', 'CCC', 'DDD', 'EEE', 'FFF', 'GGG', 'HHH', 'III'],
['1', '262', '86', '48', '8', '39', '170', '16', '4'],
['1', '56', '84', '362', '33', '82', '296', '40', '3'],
['10', '238', '149', '205', '96', '89', '223', '65', '5'],
['92', '142', '30', '237', '336', '140', '210', '50', '2']]

Transpose list of lists

Python 3:

# short circuits at shortest nested list if table is jagged:
list(map(list, zip(*l)))

# discards no data if jagged and fills short nested lists with None
list(map(list, itertools.zip_longest(*l, fillvalue=None)))

Python 2:

map(list, zip(*l))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

Explanation:

There are two things we need to know to understand what's going on:

  1. The signature of zip: zip(*iterables) This means zip expects an arbitrary number of arguments each of which must be iterable. E.g. zip([1, 2], [3, 4], [5, 6]).
  2. Unpacked argument lists: Given a sequence of arguments args, f(*args) will call f such that each element in args is a separate positional argument of f.
  3. itertools.zip_longest does not discard any data if the number of elements of the nested lists are not the same (homogenous), and instead fills in the shorter nested lists then zips them up.

Coming back to the input from the question l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]], zip(*l) would be equivalent to zip([1, 2, 3], [4, 5, 6], [7, 8, 9]). The rest is just making sure the result is a list of lists instead of a list of tuples.

How would I succinctly transpose nested lists?

use mylist = zip(*mylist):

>>> original = [[1, 2, 3, 4], [1, 2, 3, 4], [2, 3, 4, 5]]
>>> transposed = zip(*original)
>>> transposed
[(1, 1, 2), (2, 2, 3), (3, 3, 4), (4, 4, 5)]

>>> original[2][3]
5

>>> transposed[3][2]
5

How it works: zip(*original) is equal to zip(original[0], original[1], original[2]). which in turn is equal to: zip([1, 2, 3, 4], [1, 2, 3, 4], [2, 3, 4, 5]).

How to transpose a nested list in python

This is known as transposing, and you can do it like this:

lst = [('a1','b1','c1'),('a2','b2','c2'),('a3','b3','c3'),('a4','b4','c4')]
transposed_lst = list(zip(*lst))

transposed_lst evaluates to:

[('a1', 'a2', 'a3', 'a4'), ('b1', 'b2', 'b3', 'b4'), ('c1', 'c2', 'c3', 'c4')]

transpose nested list

For the specific example, you can use this pretty simple approach:

split(unlist(l), c("x", "y"))
#$x
#[1] 1 2 3
#
#$y
#[1] 4 5 6

It recycles the x-y vector and splits on that.


To generalize this to "n" elements in each list, you can use:

l = list(list(1, 4, 5), list(2, 5, 5), list(3, 6, 5)) # larger test case

split(unlist(l, use.names = FALSE), paste0("x", seq_len(length(l[[1L]]))))
# $x1
# [1] 1 2 3
#
# $x2
# [1] 4 5 6
#
# $x3
# [1] 5 5 5

This assumes, that all the list elements on the top-level of l have the same length, as in your example.

Transpose a dataframe to a nested list of list

pandas.Series.tolist() can convert series value to list.

print(input_df['continents'].unique().tolist())
print(input_df.groupby('continents', sort=False)['countries'].apply(lambda x: x.unique().tolist()).tolist())
print(input_df.groupby(['continents', 'countries'], sort=False)['cities'].apply(lambda x: [x.unique().tolist()]).tolist())
['Asia', 'America']
[['China'], ['United States', 'Canada']]
[[['Beijing', 'Shenzhen']], [['New York']], [['Toronto']]]

As for a general approach, the first approach occurred to me is to loop through the columns of df.

def list_wrapper(alist, times):
for _ in range(times):
alist = [alist]
return alist

columns_name = input_df.columns.values.tolist()
for i in range(len(columns_name)):
if i == 0:
print(input_df[columns_name[i]].unique().tolist())
else:
print(input_df.groupby(columns_name[0:i], sort=False)[columns_name[i]].apply(lambda x: list_wrapper(x.unique().tolist(), i-1)).tolist())

Transpose (rotate?) nested list

If I understand you correctly, you want to first transpose all the sublists then transpose the newly transposed groups:

print([list(zip(*sub)) for sub in zip(*l)])

Output:

In [69]: [list(zip(*sub)) for sub in zip(*l)]
Out[69]: [[('a', 'e'), ('b', 'f')], [('c', 'g'), ('d', 'h')]]

If you want some map foo with a lambda:

In [70]: list(map(list, map(lambda x: zip(*x), zip(*l))))
Out[70]: [[('a', 'e'), ('b', 'f')], [('c', 'g'), ('d', 'h'

For python2 you don't need the extra map call but I would use itertools.izip to do the initial transpose.:

In [9]: from itertools import izip

In [10]: map(lambda x: zip(*x), izip(*l))
Out[10]: [[('a', 'e'), ('b', 'f')], [('c', 'g'), ('d', 'h')]]

Return values from nested lists into PandasDataFrame

A simple way to do this is by converting the list into a dictionary and then creating a Data Frame from that dictionary as explained below:

l =[[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]

# Creating a dictionary using dictionary comprehension
d = {'col'+str(i) : l[i] for i in range(len(l))}

df = pd.DataFrame(d)

output



Related Topics



Leave a reply



Submit