从Numpy 3D数组高效地创建Pandas DataFrame

13

假设我们从这里开始

import numpy as np
a = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])

如何将此有效地转换为 Pandas DataFrame,与以下相当:

import pandas as pd
>>> pd.DataFrame({'a': [0, 0, 1, 1], 'b': [1, 3, 5, 7], 'c': [2, 4, 6, 8]})

   a  b  c
0  0  1  2
1  0  3  4
2  1  5  6
3  1  7  8

这个想法是让 a 列成为原始数组第一维的索引,其余列则是原始数组后两个维度中2D数组的垂直连接。

(这可以通过循环轻松完成; 问题是如何在没有循环的情况下完成。)


较长示例

使用 @Divakar 的卓越建议:

>>> np.random.randint(0,9,(4,3,2))
array([[[0, 6],
    [6, 4],
    [3, 4]],

   [[5, 1],
    [1, 3],
    [6, 4]],

   [[8, 0],
    [2, 3],
    [3, 1]],

   [[2, 2],
    [0, 0],
    [6, 3]]])

应该将其改为类似于:

>>> pd.DataFrame({
    'a': [0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3], 
    'b': [0, 6, 3, 5, 1, 6, 8, 2, 3, 2, 0, 6], 
    'c': [6, 4, 4, 1, 3, 4, 0, 3, 1, 2, 0, 3]})
    a  b  c
0   0  0  6
1   0  6  4
2   0  3  4
3   1  5  1
4   1  1  3
5   1  6  4
6   2  8  0
7   2  2  3
8   2  3  1
9   3  2  2
10  3  0  0
11  3  6  3

那个样例不应该是'b': [1, 3, 5, 7]吗?另外,你能否添加另一个样例,例如a = np.random.randint(0,9,(4,3,2)),以便查看当维度长度不同时会发生什么? - Divakar
@Divakar 感谢您的精彩评论! - Ami Tavory
3个回答

26

这里有一种方法,先在NumPy上进行大部分处理,最后将其作为DataFrame输出,如下所示 -

m,n,r = a.shape
out_arr = np.column_stack((np.repeat(np.arange(m),n),a.reshape(m*n,-1)))
out_df = pd.DataFrame(out_arr)

如果您确切地知道列的数量将为2,那么我们将有bc作为最后两列,a作为第一列,您可以像这样添加列名称 -

out_df = pd.DataFrame(out_arr,columns=['a', 'b', 'c'])

示例运行 -

>>> a
array([[[2, 0],
        [1, 7],
        [3, 8]],

       [[5, 0],
        [0, 7],
        [8, 0]],

       [[2, 5],
        [8, 2],
        [1, 2]],

       [[5, 3],
        [1, 6],
        [3, 2]]])
>>> out_df
    a  b  c
0   0  2  0
1   0  1  7
2   0  3  8
3   1  5  0
4   1  0  7
5   1  8  0
6   2  2  5
7   2  8  2
8   2  1  2
9   3  5  3
10  3  1  6
11  3  3  2

谢谢!这很好用。虽然,我用 x、y、z 替换了 m、n、r。 - Abe Hoffman
我发现的将3D数组传递给pandas数据框的最佳解决方案!! - dbz
5
自从pandas v0.25.0中删除了面板对象(Panel Object),因此这可能会成为官方答案。 - Drafter250

5

使用 Panel

a = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
b=pd.Panel(rollaxis(a,2)).to_frame()
c=b.set_index(b.index.labels[0]).reset_index()
c.columns=list('abc')

那么a是:

[[[1 2]
  [3 4]]

 [[5 6]
  [7 8]]]

b 是:

             0  1
major minor      
0     0      1  2
      1      3  4
1     0      5  6
      1      7  8

并且 c 是 :

   a  b  c
0  0  1  2
1  0  3  4
2  1  5  6
3  1  7  8

5
Panel已被弃用,请参见@Divakar的回答。 - mloning

1
这是一个纯Pandas的解决方案,没有使用Panels。
要获取带有MultiIndex的数据框,请使用pd.concat
>>> df = pd.concat([pd.DataFrame(arr) for arr in a], keys=np.arange(len(a)))
>>> df
     0  1
0 0  0  6
  1  6  4
  2  3  4
1 0  5  1
  1  1  3
  2  6  4
2 0  8  0
  1  2  3
  2  3  1
3 0  2  2
  1  0  0
  2  6  3

要将其转换为问题中提供的非MultiIndex形式:

>>> df.reset_index().drop('level_1',axis=1).set_axis(['a','b','c'], axis=1)

    a  b  c
0   0  0  6
1   0  6  4
2   0  3  4
3   1  5  1
4   1  1  3
5   1  6  4
6   2  8  0
7   2  2  3
8   2  3  1
9   3  2  2
10  3  0  0
11  3  6  3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接