【问题标题】:How to convert a list of lists into a dataframe in python如何在python中将列表列表转换为数据框
【发布时间】:2018-10-30 10:05:19
【问题描述】:

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

[['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 还很陌生,所以我很难过。

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

【问题讨论】:

    标签: python list pandas dataframe


    【解决方案1】:

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

    我们使用 2 个基本习语:

    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
    

    【讨论】:

    • 我已经检查了所有的解决方案,这确实是最快的 :) 但无论如何我这次要给 wen。在我的旅程中继续支持我。我真的很感激
    • @AhamedMoosa,别担心,我也喜欢 Wen 的解决方案 :)。
    【解决方案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
    

    【讨论】:

    • 这简直太棒了 +1。但可能不如itertools.chain 快:)。
    • 谢谢文,我应该说太棒了。有你和周围的其他人,我很快就能掌握 Python
    • @AhamedMoosa,请注意,您可能正在掌握pandas,但这绝不等同于python。只是一个友好的提醒:)。
    • @jpp 我希望从一开始就掌握 pandas,是的,正如你所说的那样,python 是一片海洋,如果我尝试冲浪,我可能会下沉 :) 但你们太棒了 :)
    【解决方案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):
    

    一次循环遍历data 的 5 项。


    pd.concat 可以接受 dict 的 DataFrames 作为输入,并将它们连接成单个 DataFrame,其中 MultiIndex 由 dict 的键组成。 所以for-loop用来组成DataFrames的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。

    【讨论】:

    • 感谢 unutbu 的回答、建议和教育我。我真的很感谢你的帮助。该代码非常适合我的目标
    猜你喜欢
    • 1970-01-01
    • 2016-02-05
    • 2021-10-16
    • 1970-01-01
    • 2020-07-23
    • 2019-11-16
    • 2021-12-13
    • 1970-01-01
    相关资源
    最近更新 更多