将 x 个相同大小的 2D numpy 数组转换为 2+x 列数据框

Convert x same size 2D numpy arrays to a 2+x column data frame

我有两个大小为 (m x n) 的 ndarray,以及两个长度分别为 m 和 n 的列表。我想将这两个矩阵转换为具有四列的数据框。前两列对应于 m 和 n 维度,并包含列表中的值。接下来的两列应包含来自两个矩阵的值。总的来说,生成的数据框应该有 m 乘以 n 行。

示例: 如果这些是两个矩阵和两个列表,

a1 = np.array([[1, 2], [3, 4],[5,6]])
a2 = np.array([[10, 20], [30, 40],[50,60]])
l1 = [5,7,99]
l2 = [2,3]

那么生成的数据框应该如下所示:

"l1" "l2" "a1" "a2"
5    2    1    10
7    2    3    30
99   2    5    50
5    3    2    20
7    3    4    40
99   3    6    60

行的顺序无关紧要。

虽然在这种特定情况下我只有两个矩阵,但我很好奇可以轻松适用于任意数量的相同大小矩阵的解决方案。

使用np.vstack for join arrays created by numpy.tile, numpy.repeat and numpy.ravel并传递给DataFrame构造函数:

a = np.vstack((np.tile(l1, len(l2)),
               np.repeat(l2, len(l1)),
               np.ravel(a1, 'F'), 
               np.ravel(a2, 'F'))).T
print (a)
[[ 5  2  1 10]
 [ 7  2  3 30]
 [99  2  5 50]
 [ 5  3  2 20]
 [ 7  3  4 40]
 [99  3  6 60]]


df = pd.DataFrame(a, columns=['l1','l2','a1','a2'])
print (df)
   l1  l2  a1  a2
0   5   2   1  10
1   7   2   3  30
2  99   2   5  50
3   5   3   2  20
4   7   3   4  40
5  99   3   6  60

对于多个数组:

arrays =  [a1, a2]

arr = [np.ravel(a, 'F') for a in arrays]
a = np.vstack((np.tile(l1, len(l2)), 
               np.repeat(l2, len(l1)),
               arr)).T
print (a)
[[ 5  2  1 10]
 [ 7  2  3 30]
 [99  2  5 50]
 [ 5  3  2 20]
 [ 7  3  4 40]
 [99  3  6 60]]


df = pd.DataFrame(a, columns=['l1','l2'] + [f'a{x+1}' for x in range(len(arrays))])
print (df)
   l1  l2  a1  a2
0   5   2   1  10
1   7   2   3  30
2  99   2   5  50
3   5   3   2  20
4   7   3   4  40
5  99   3   6  60

Pandas 只有 concat and DataFrame.unstack 的解决方案:

df = (pd.concat([pd.DataFrame(a1, columns=l2, index=l1).unstack(),
                pd.DataFrame(a2, columns=l2, index=l1).unstack()],
               axis=1, keys=['a1','a2'])
        .rename_axis(['l2','l1']).swaplevel(1,0).reset_index())
print (df)
   l1  l2  a1  a2
0   5   2   1  10
1   7   2   3  30
2  99   2   5  50
3   5   3   2  20
4   7   3   4  40
5  99   3   6  60

对于多个数组:

arrays =  [a1, a2]
df = (pd.concat([pd.DataFrame(a, columns=l2, index=l1).unstack() for a in arrays],
               axis=1)
        .rename_axis(['l2','l1'])
        .swaplevel(1,0)
        .rename(columns=lambda x: f'a{x+1}')
        .reset_index())
print (df)
   l1  l2  a1  a2
0   5   2   1  10
1   7   2   3  30
2  99   2   5  50
3   5   3   2  20
4   7   3   4  40
5  99   3   6  60

扩展 jezrael 对多个数组的出色回答:

arrays = ... # e.g [a1, a2]
a = np.vstack([np.tile(l1, len(l2), 
               np.repeat(l2, len(l1))] + 
              [np.ravel(a, 'F') for a in arrays]).T

这应该可以解决您的问题:

import pandas as pd
import numpy as np
df=pd.DataFrame()
a1 = np.array([[1, 2], [3, 4],[5,6]])
a2 = np.array([[10, 20], [30, 40],[50,60]])
l1 = [5,7,99]
l2 = [2,3]
m,n=len(l1),len(l2)
temp_l1=[]
for i in l1:
    temp_l1.extend([i]*n)
df["l1"]=temp_l1
df["l2"]=l2*m
df["a1"]=a1.flatten()
df["a2"]=a2.flatten()
print(df)

输出:

   l1  l2  a1  a2
0   5   2   1  10
1   5   3   2  20
2   7   2   3  30
3   7   3   4  40
4  99   2   5  50
5  99   3   6  60