我有几个2D numpy数组(矩阵),我希望将它转换为包含数组值的向量和包含每个行/列索引的向量。
例如,我可能有这样的数组:
x = np.array([[3, 1, 4],
[1, 5, 9],
[2, 6, 5]])
我基本上想要值
[3, 1, 4, 1, 5, 9, 2, 6, 5]
和他们的位置
[[0,0], [0,1], [0,2], [1,0], [1,1], [1,2], [2,0], [2,1], [2,2]]
我的最终目标是将这些放入pandas DataFrame中,如下所示:
V | x | y
--+---+---
3 | 0 | 0
1 | 0 | 1
4 | 0 | 2
1 | 1 | 0
5 | 1 | 1
9 | 1 | 2
6 | 2 | 0
5 | 2 | 1
3 | 2 | 2
其中V是值,x是行位置(索引),y是列位置(索引)。
我想我可以一起破解一些东西,但我试图找到有效的方法来做到这一点,而不是摸索。例如,我知道我可以使用类似x.reshape(x.size, 1)
的内容来获取值,并且我可以尝试从x.shape
创建索引列,但似乎应该有更好的方法。
答案 0 :(得分:7)
我不知道它是否效率最高,但numpy.meshgrid
是为此设计的:
x = np.array([[3, 1, 4],
[1, 5, 9],
[2, 6, 5]])
XX,YY = np.meshgrid(np.arange(x.shape[1]),np.arange(x.shape[0]))
table = np.vstack((x.ravel(),XX.ravel(),YY.ravel())).T
print table
这会产生:
[[3 0 0]
[1 1 0]
[4 2 0]
[1 0 1]
[5 1 1]
[9 2 1]
[2 0 2]
[6 1 2]
[5 2 2]]
然后我认为df = pandas.DataFrame(table)
会为您提供所需的数据框。
答案 1 :(得分:1)
你也可以让pandas为你工作,因为你将在数据帧中使用它:
x = np.array([[3, 1, 4],
[1, 5, 9],
[2, 6, 5]])
df=pd.DataFrame(x)
#unstack the y columns so that they become an index then reset the
#index so that indexes become columns.
df=df.unstack().reset_index()
df
level_0 level_1 0
0 0 0 3
1 0 1 1
2 0 2 2
3 1 0 1
4 1 1 5
5 1 2 6
6 2 0 4
7 2 1 9
8 2 2 5
#name the columns and switch the column order
df.columns=['x','y','V']
cols = df.columns.tolist()
cols = cols[-1:] + cols[:-1]
df = df[cols]
df
V x y
0 3 0 0
1 1 0 1
2 2 0 2
3 1 1 0
4 5 1 1
5 6 1 2
6 4 2 0
7 9 2 1
8 5 2 2
答案 2 :(得分:1)
类np.ndindex
专门用于此目的,并且很容易实现。效率与上面的np.mesgrid
方法相似,但是所需的代码更少:
indices = np.array(list(np.ndindex(x.shape)))
对于数据框,请执行以下操作:
df = pd.DataFrame({'V': x.flatten(), 'x': indices[:, 0], 'y': indices[:, 1]})
如果不需要数据框,只需执行list(np.ndindex(x.shape))
。
注意:请不要混淆x
(手头的数组)和'x'
(第二列的名称)。
我知道这个问题是很久以前发布的,但以防万一它对任何人都有用,因为我没有提到np.ndindex
。
答案 3 :(得分:0)
你可以简单地使用循环。
x = np.array([[3, 1, 4],
[1, 5, 9],
[2, 6, 5]])
values = []
coordinates = []
data_frame = []
for v in xrange(len(x)):
for h in xrange(len(x[v])):
values.append(x[v][h])
coordinates.append((h, v))
data_frame.append(x[v][h], h, v)
print '%s | %s | %s' % (x[v][h], v, h)
答案 4 :(得分:0)
您可以使用itertools
import itertools
import numpy as np
import pandas as pd
def convert2dataframe(array):
a, b = array.shape
x, y = zip(*list(itertools.product(range(a), range(b))))
df = pd.DataFrame(data={'V':array.ravel(), 'x':x, 'y':y})
return df
这适用于任何形状的数组,不一定是方形矩阵。
答案 5 :(得分:0)
另一种方式:
arr = np.array([[3, 1, 4],
[1, 5, 9],
[2, 6, 5]])
# build out rows array
x = np.arange(arr.shape[0]).reshape(arr.shape[0],1).repeat(arr.shape[1],axis=1)
# build out columns array
y = np.arange(arr.shape[1]).reshape(1,arr.shape[0]).repeat(arr.shape[0],axis=0)
# combine into table
table = np.vstack((arr.reshape(arr.size),x.reshape(arr.size),y.reshape(arr.size))).T
print table
答案 6 :(得分:0)
我正在复活这是因为我想我知道一个更容易理解的不同答案。这是我的方法:
xn
在[[ 3. 0. 0.]
[ 1. 0. 1.]
[ 4. 0. 2.]
[ 1. 1. 0.]
[ 5. 1. 1.]
[ 9. 1. 2.]
[ 2. 2. 0.]
[ 6. 2. 1.]
[ 5. 2. 2.]]
中,我们有
{{1}}
答案 7 :(得分:0)
2020年11月更新(已在pandas v1.1.3和numpy v1.19上测试):
使用np.meshgrid和}
应该很容易。
.reshape(-1)
对于二维情况,您甚至不需要网格。只需np.tile的列轴范围和np.repeat的行轴。
x = np.array([[3, 1, 4],
[1, 5, 9]])
x_coor, y_coor = np.meshgrid(range(x.shape[1]), range(x.shape[0]))
df = pd.DataFrame({"V": x.reshape(-1), "x": x_coor.reshape(-1), "y": y_coor.reshape(-1)})
将示例数据修剪为df = pd.DataFrame({
"V": x.reshape(-1),
"x": np.tile(np.arange(x.shape[1]), x.shape[0]),
"y": np.repeat(np.arange(x.shape[0]), x.shape[1])
})
,以更好地反映轴的位置。
结果
shape=(2, 3)
答案 8 :(得分:0)
像@miguel-capllonch 一样,我建议使用 np.ndindex
,它允许您像这样创建所需的输出:
np.array([(v, *i) for (i, v) in zip(np.ndindex(x.shape), x.ravel())])
结果是一个如下所示的数组:
array([[ 3. 0. 0.]
[ 1. 0. 1.]
[ 4. 0. 2.]
[ 1. 1. 0.]
[ 5. 1. 1.]
[ 9. 1. 2.]
[ 2. 2. 0.]
[ 6. 2. 1.]
[ 5. 2. 2.]])
或者,仅使用 numpy 命令
np.hstack((list(np.ndindex(x.shape)), x.reshape((-1, 1))))
答案 9 :(得分:0)
这基本上是 x.ravel()
和笛卡尔索引之间的串联:
np.c_[x.ravel(), np.c_[np.repeat(np.r_[:3], 3), np.tile(np.r_[:3], 3)]]
输出:
array([[3, 0, 0],
[1, 0, 1],
[4, 0, 2],
[1, 1, 0],
[5, 1, 1],
[9, 1, 2],
[2, 2, 0],
[6, 2, 1],
[5, 2, 2]])