压扁numpy数组还要保持价值位置的指数?

时间:2015-06-26 19:50:39

标签: python arrays numpy

我有几个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创建索引列,但似乎应该有更好的方法。

10 个答案:

答案 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]])