【问题标题】:Convert DataFrame or Series of lists into one stacked DataFrame (or Series)将 DataFrame 或 Series 列表转换为一个堆叠的 DataFrame(或 Series)
【发布时间】:2018-04-19 20:03:54
【问题描述】:

有一个由列表组成的DataFrame(或Series),如下所示:

df = pd.DataFrame([[[1,3], [2,3,4], [1,4,2,5]]], columns=['A', 'B', 'C']).T
print(df)

输出:

              0
A        [1, 3]
B     [2, 3, 4]
C  [1, 4, 2, 5]

我怎样才能把它变成

   0
A  1
A  2
B  2
B  3 
B  4
C  1
C  4
C  2 
C  5

我尝试使用apply(),但效果不佳。我可以隐式转换吗?我还尝试将所有数字提取为 [('A', 1), ('A', 3), ..] 的元组 from_records(),但我也无法做到这一点。

我想我可以这样做:

pd.DataFrame.from_records(df[0].map(lambda x: [(0, v) for v in x]).sum())

但我不知道如何访问索引。注意(0, v) 实际上应该类似于(x.index, v)

【问题讨论】:

    标签: python list pandas dataframe flatten


    【解决方案1】:

    需要展平列中的值,然后按lenlists 索引repeat

    df = pd.DataFrame({0:np.concatenate(df.iloc[:, 0].values.tolist())},
                      index=df.index.repeat(df[0].str.len()))
    

    from  itertools import chain
    df=pd.DataFrame({0:list(chain.from_iterable(df.iloc[:, 0].values.tolist()))}, 
                     index=df.index.repeat(df[0].str.len()))
    

    print (df)
       0
    A  1
    A  3
    B  2
    B  3
    B  4
    C  1
    C  4
    C  2
    C  5
    

    时间安排

    np.random.seed(456)
    
    N = 100000
    a = [list(range(np.random.randint(5, 20))) for _ in range(N)]
    L = list('abcdefghijklmno') 
    df = pd.DataFrame({0:a}, index=np.random.choice(L, size=N))
    print (df)
    
    In [348]: %timeit pd.DataFrame({0:np.concatenate(df.iloc[:, 0].values.tolist())}, index=df.index.repeat(df[0].str.len()))
    1 loop, best of 3: 218 ms per loop
    
    In [349]: %timeit pd.DataFrame({0:list(chain.from_iterable(df[0].values.tolist()))}, index=df.index.repeat(df[0].str.len()))
    1 loop, best of 3: 388 ms per loop
    
    In [350]: %timeit pd.DataFrame(df.iloc[:, 0].tolist(), index=df.index).stack().reset_index(level=1, drop=1).to_frame().astype(int)
    1 loop, best of 3: 384 ms per loop
    

    【讨论】:

    • 我已经用一个使用from_records() 的示例更新了我的问题,但问题是当我使用map() 时我无法访问每个元素的实际索引......任何想法如果它可以这样工作?
    • 嗯,这是不可能的:(
    • @displayname 请注意,我的回答涉及完整性,所以如果您有任何性能问题,请考虑查看 jezrael 的第一个选项 :-)
    • @cᴏʟᴅsᴘᴇᴇᴅ 感谢您的提示。事实上,我在那里遇到了性能问题。我也会看看 jezrael 的答案。
    • @displayname - 我对其进行了测试,对于更大的数据帧来说,第一个解决方案是更快的。还添加了时间来回答。
    【解决方案2】:

    使用pd.DataFrame + stack + reset_index + to_frame

    df = pd.DataFrame(df.iloc[:, 0].tolist(), index=df.index)\
                             .stack().reset_index(level=1, drop=1).to_frame()
    df
    
         0
    A  1.0
    A  3.0
    B  2.0
    B  3.0
    B  4.0
    C  1.0
    C  4.0
    C  2.0
    C  5.0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-09
      • 2016-12-28
      • 1970-01-01
      • 2021-07-26
      • 1970-01-01
      • 2017-08-08
      • 2012-05-09
      • 1970-01-01
      相关资源
      最近更新 更多