如何将列表列表转换为python

时间:2018-05-20 16:44:28

标签: python list pandas dataframe

我有一个列表如下:

[['A'],
 ['America'],
 ['2017-39', '2017-40', '2017-41', '2017-42', '2017-43'],
 [10.0, 6.0, 6.0, 6.0, 1.0],
 [5.0,7.0,8.0,9.0,1.0],
 ,
 ['B'],
 ['Britan'],
 ['2017-38', '2017-39', '2017-40', '2017-41', '2017-42', '2017-43', '2017-44'],
 [41.0, 27.0, 38.0, 36.0, 33.0, 41.0, 8.0],
 [40.0, 38.0, 28.0, 27.0, 23.0, 65.0, 4.0]]

我想将其转换为应该看起来像

的数据框
A America     2017-39   10.0  5.0
na   na       2017-40    6.0  7.0
na   na       2017-41    6.0  8.0
na   na       2017-42    6.0  9.0
na   na       2017-43    1.0 10.0
B Britan      2017-38   41.0 40.0
na   na       2017-39   27.0 38.0
na   na       2017-40   38.0 28.0
na   na       2017-41   36.0 27.0
na   na       2017-42   33.0 23.0
na   na       2017-43   41.0 65.0
na   na       2017-44    8.0  4.0

我如何编写代码使其成为可能,因为我对python很新,我很难。

我将非常感谢您在这方面帮助我的时间和精力

3 个答案:

答案 0 :(得分:3)

import pandas as pd
data = [['A'],
 ['America'],
 ['2017-39', '2017-40', '2017-41', '2017-42', '2017-43'],
 [10.0, 6.0, 6.0, 6.0, 1.0],
 [5.0,7.0,8.0,9.0,1.0],
 ['B'],
 ['Britan'],
 ['2017-38', '2017-39', '2017-40', '2017-41', '2017-42', '2017-43', '2017-44'],
 [41.0, 27.0, 38.0, 36.0, 33.0, 41.0, 8.0],
 [40.0, 38.0, 28.0, 27.0, 23.0, 65.0, 4.0]]

result = {}
for letters, countries, dates, val1, val2 in zip(*[iter(data)]*5):
    result[tuple(letters+countries)] = pd.DataFrame({'date':dates, 'val1':val1, 'val2':val2})
result = pd.concat(result)
print(result)

产量

                date  val1  val2
A America 0  2017-39  10.0   5.0
          1  2017-40   6.0   7.0
          2  2017-41   6.0   8.0
          3  2017-42   6.0   9.0
          4  2017-43   1.0   1.0
B Britan  0  2017-38  41.0  40.0
          1  2017-39  27.0  38.0
          2  2017-40  38.0  28.0
          3  2017-41  36.0  27.0
          4  2017-42  33.0  23.0
          5  2017-43  41.0  65.0
          6  2017-44   8.0   4.0

上面的主要想法是使用"grouper idiom" zip(*[iter(data)]*5)data中的项目分组为5.这样,就可以使用

for letters, countries, dates, val1, val2 in zip(*[iter(data)]*5):

一次循环浏览5个data项。

pd.concat可以接受dict个DataFrame作为输入,并将它们连接到一个DataFrame中,其中MultiIndex由dict的键组成。 因此,for-loop用于撰写数据框的dict

for letters, countries, dates, val1, val2 in zip(*[iter(data)]*5):
    result[tuple(letters+countries)] = pd.DataFrame({'date':dates, 'val1':val1, 'val2':val2})

然后

result = pd.concat(result)

生成所需的DataFrame。

不是说你可以删除MultiIndex的最后一个级别:

In [91]: result.index = result.index.droplevel(level=-1)

In [92]: result
Out[92]: 
              date  val1  val2
A America  2017-39  10.0   5.0
  America  2017-40   6.0   7.0
  America  2017-41   6.0   8.0
  America  2017-42   6.0   9.0
  America  2017-43   1.0   1.0
B Britan   2017-38  41.0  40.0
  Britan   2017-39  27.0  38.0
  Britan   2017-40  38.0  28.0
  Britan   2017-41  36.0  27.0
  Britan   2017-42  33.0  23.0
  Britan   2017-43  41.0  65.0
  Britan   2017-44   8.0   4.0

但我不建议这样做,因为它使索引非唯一:

In [96]: result.index.is_unique
Out[96]: False

这可能会导致未来的困难,因为一些Pandas操作只能处理具有唯一索引的DataFrame。

答案 1 :(得分:2)

一种解决方案是使用itertools执行一些链接魔法。

我们使用了两个必要的习语:

  1. 对于标识列,zip数据列表的长度以及标识符。
  2. 对于数据列,请使用chain.from_iterable(分配给chainer)合并每个第5个子列表。
  3. 在这两种情况下,我们都会使用islice来避免不必要地创建列表作为中间步骤。

    data定义为@ unutbu的帖子。

    <强>解决方案

    import pandas as pd
    from itertools import chain, islice
    
    chainer = chain.from_iterable
    
    lens = list(map(len, islice(data, 2, None, 5)))
    
    res = pd.DataFrame({'id1': list(chainer(list(j)+[np.nan]*(i-1) for i, j in
                                    zip(lens, islice(data, 0, None, 5)))),
                        'id2': list(chainer(list(j)+[np.nan]*(i-1) for i, j in 
                                    zip(lens, islice(data, 1, None, 5)))),
                        'date': list(chainer(islice(data, 2, None, 5))),
                        'num1': list(chainer(islice(data, 3, None, 5))),
                        'num2': list(chainer(islice(data, 4, None, 5)))})
    
    res = res[['id1', 'id2', 'date', 'num1', 'num2']]
    

    <强>结果

    print(res)
    
        id1      id2     date  num1  num2
    0     A  America  2017-39  10.0   5.0
    1   NaN      NaN  2017-40   6.0   7.0
    2   NaN      NaN  2017-41   6.0   8.0
    3   NaN      NaN  2017-42   6.0   9.0
    4   NaN      NaN  2017-43   1.0   1.0
    5     B   Britan  2017-38  41.0  40.0
    6   NaN      NaN  2017-39  27.0  38.0
    7   NaN      NaN  2017-40  38.0  28.0
    8   NaN      NaN  2017-41  36.0  27.0
    9   NaN      NaN  2017-42  33.0  23.0
    10  NaN      NaN  2017-43  41.0  65.0
    11  NaN      NaN  2017-44   8.0   4.0
    

答案 2 :(得分:2)

我正在使用groupby并重新创建列

s=pd.DataFrame(lst).T
s.columns=s.columns//5
pd.concat([pd.DataFrame(x.values) for _,x in s.groupby(level=0,axis=1)]).dropna(axis=0,thresh=1)
Out[146]: 
      0        1        2   3   4
0     A  America  2017-39  10   5
1  None     None  2017-40   6   7
2  None     None  2017-41   6   8
3  None     None  2017-42   6   9
4  None     None  2017-43   1   1
0     B   Britan  2017-38  41  40
1  None     None  2017-39  27  38
2  None     None  2017-40  38  28
3  None     None  2017-41  36  27
4  None     None  2017-42  33  23
5  None     None  2017-43  41  65
6  None     None  2017-44   8   4