代码之家  ›  专栏  ›  技术社区  ›  Ahamed Moosa

如何在python中将列表列表转换为数据帧

  •  2
  • Ahamed Moosa  · 技术社区  · 7 年前

    我有一个列表,如下所示:

    [['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 回复  |  直到 7 年前
        1
  •  2
  •   BENY    7 年前

    我正在使用 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
    
        2
  •  3
  •   unutbu    7 年前
    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项 数据 一次。


    pd.concat 可以接受 dict 将数据帧作为输入并将其连接到一个具有由 双关语 . 所以 for-loop 用于组成 双关语 数据帧,

    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)
    

    生成所需的数据帧。


    不是说您可以删除多索引的最后一个级别:

    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
    

    这可能会造成未来的困难,因为一些熊猫操作只在具有唯一索引的数据帧上工作。

        3
  •  2
  •   jpp    7 年前

    一种解决方案是使用 itertools 做一些链子魔术。

    我们使用了两个基本的习语:

    1. 对于标识符列, zip 数据列表的长度以及标识符。
    2. 对于数据列,请使用 chain.from_iterable (分配给 chainer )每5个子列表合并一次。

    在这两种情况下,我们都利用 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