【问题标题】:Iterate over pandas dataframe columns containing nested arrays迭代包含嵌套数组的 pandas 数据框列
【发布时间】:2020-09-28 17:31:06
【问题描述】:

希望你能帮我解决这个问题,

我在下面有这些数据(列名随便)

data=([['file0090',
    ([[ 84,  55, 189],
   [248, 100,  18],
   [ 68, 115,  88]])],
   ['file6565',
    ([[ 86,  58, 189],
   [24, 10,  118],
   [ 68, 11,  8]])
   ]])

我需要将第 0 列和第 1 列迭代到排序列表中,我可以转换为 Dataframe 使用此输出:

col0          col1  col2   col3 
file0090      84     55     189
file0090      248    100      1
file0090      68     115    88
file6565      86     58    189
file6565      24    10     118
file6565      68    11      8

我已经使用 iterrows、iteritems、items 测试了所有数据帧迭代, 并追加到一个列表中,但结果总是围绕相同的输出,我不知道这些数组中的项目是如何分开的

如果您能提供帮助,请提前感谢您。

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    我们可以用行做explode,然后再用列爆炸

    s = pd.DataFrame(data).set_index(0)[1].explode()
    df = pd.DataFrame(s.tolist(), index = s.index.values)
    
    df
    Out[396]: 
                0    1    2
    file0090   84   55  189
    file0090  248  100   18
    file0090   68  115   88
    file6565   86   58  189
    file6565   24   10  118
    file6565   68   11    8
    

    【讨论】:

      【解决方案2】:

      在从一系列列表中创建另一个 df 之后,您可以使用 join 执行 explode

      df = pd.DataFrame(data).add_prefix('col')
      
      out = df.explode('col1').reset_index(drop=True)
      out = out.join(pd.DataFrame(out.pop('col1').tolist()).add_prefix('col_'))
      

      如果列表结构相似,则添加另一个解决方案:

      l = [*itertools.chain.from_iterable(data)]
      pd.DataFrame(np.vstack(l[1::2]),index = np.repeat(l[::2],len(l[1])))
      

            col0  col_0  col_1  col_2
      0  file0090     84     55    189
      1  file0090    248    100     18
      2  file0090     68    115     88
      3  file6565     86     58    189
      4  file6565     24     10    118
      5  file6565     68     11      8
      

      【讨论】:

        【解决方案3】:

        你可以试试这个:-

        data_f = [[i[0]]+j for i in data for j in i[1]]
        df = pd.DataFrame(data_f, columns =['col0','col1','col2','col3'])
        

        输出:-

        col0          col1  col2   col3 
        file0090      84     55     189
        file0090      248    100      1
        file0090      68     115    88
        file6565      86     58    189
        file6565      24    10     118
        file6565      68    11      8
        

        【讨论】:

        • 使用 %%timeit 这个解决方案胜过@YOBEN_S 解决方案。循环并不总是坏事的一个证明。
        • 同意@Scott,猜想我们可以使用data_f = [[i[0]]+j for i in data for j in i[1] ] list comp 之类的东西应该更快..?
        • @ScottBoston 也许使用更大的数据可能会更慢。就像 anky 建议的那样,在这里使用 list comp 是更好的选择。
        • 同意,列表理解更快。更改了代码。谢谢大家的建议
        【解决方案4】:

        您可以创建自定义函数来输出正确形式的数据。

        from itertools import chain
        def transform(d):
            for l in d:
                *x, y = l
                yield list(map(lambda s: x+s, y))
        
        df = pd.DataFrame(chain(*transform(data)))
        df
                  0    1    2    3
        0  file0090   84   55  189
        1  file0090  248  100   18
        2  file0090   68  115   88
        3  file6565   86   58  189
        4  file6565   24   10  118
        5  file6565   68   11    8
        

        所有解的Timeit结果:

        # YOBEN_S's answer
        In [275]: %%timeit
             ...: s = pd.DataFrame(data).set_index(0)[1].explode()
             ...: df = pd.DataFrame(s.tolist(), index = s.index.values)
             ...:
             ...:
        1.52 ms ± 59.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
        
        #Anky's answer
        In [276]: %%timeit
             ...: df = pd.DataFrame(data).add_prefix('col')
             ...: out = df.explode('col1').reset_index(drop=True)
             ...: out = out.join(pd.DataFrame(out.pop('col1').tolist()).add_prefix('col_'))
             ...:
             ...:
        3.71 ms ± 606 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
        
        #Dhaval's answer
        In [277]: %%timeit
             ...: data_f = []
             ...: for i in data:
             ...:     for j in i[1]:
             ...:         data_f.append([i[0]]+j)
             ...: df = pd.DataFrame(data_f, columns =['col0','col1','col2','col3'])
             ...:
             ...:
        712 µs ± 24.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
        
        #My answer
        In [280]: %%timeit
             ...: pd.DataFrame(chain(*transform(data)))
             ...:
             ...:
        489 µs ± 8.91 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
        
        #Using List comp of Dhaval's answer
        
        In [306]: %%timeit
             ...: data_f = [[i[0]]+j for i in data for j in i[1]]
             ...: df = pd.DataFrame(data_f, columns =['col0','col1','col2','col3'])
             ...:
             ...:
        586 µs ± 25 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
        
        #Anky's 2nd solution
        
        In [308]: %%timeit
             ...: l = [*chain.from_iterable(data)]
             ...: pd.DataFrame(np.vstack(l[1::2]),index = np.repeat(l[::2],len(l[1])))
             ...:
             ...:
        221 µs ± 18.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
        

        【讨论】:

        • 确实非常好(已经投票了),你能不能也为 list comp 添加时间,只是好奇
        • @anky 添加了它。使用 list comp 将时间缩短了约 100µs。
        • @anky 谢谢。我喜欢这里介绍的每种方法(都赞成),将添加您发布的新解决方案的 timeit 结果。
        • @anky 最快的解决方案只有 220µs。非常酷的解决方案,不幸的是,我只能投票一次:p
        猜你喜欢
        • 1970-01-01
        • 2015-01-30
        • 2017-01-04
        • 1970-01-01
        • 2013-04-30
        • 1970-01-01
        • 2019-11-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多