将MxN二维数据点阵列重组为一个N维数组

时间:2015-08-20 22:37:03

标签: python numpy multidimensional-array

我在2D阵列中进行了一系列测量,例如

T    mu1  mu2  mu3  a    b    c    d    e
0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  1.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  2.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  3.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  1.0  0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  1.0  1.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  1.0  2.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  1.0  3.0  0.0  0.0  0.0  0.0  0.0
0.0  1.0  2.0  0.0  0.0  0.0  0.0  0.0  0.0
0.0  1.0  2.0  1.0  0.0  0.0  0.0  0.0  0.0
0.0  1.0  2.0  2.0  0.0  0.0  0.0  0.0  0.0
0.0  1.0  2.0  3.0  0.0  0.0  0.0  0.0  0.0
0.0  1.0  3.0  0.0  0.0  0.0  0.0  0.0  0.0
0.0  1.0  3.0  1.0  0.0  0.0  0.0  0.0  0.0
0.0  1.0  3.0  2.0  0.0  0.0  0.0  0.0  0.0
0.0  1.0  3.0  3.0  0.0  0.0  0.0  0.0  0.0
1.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0
1.0  0.0  0.0  1.0  0.0  0.0  0.0  0.0  0.0
1.0  0.0  0.0  2.0  0.0  0.0  0.0  0.0  0.0
1.0  0.0  0.0  3.0  0.0  0.0  0.0  0.0  0.0
1.0  0.0  1.0  0.0  0.0  0.0  0.0  0.0  0.0
1.0  0.0  1.0  1.0  0.0  0.0  0.0  0.0  0.0
1.0  0.0  1.0  2.0  0.0  0.0  0.0  0.0  0.0
1.0  0.0  1.0  3.0  0.0  0.0  0.0  0.0  0.0
1.0  1.0  2.0  0.0  0.0  0.0  0.0  0.0  0.0
1.0  1.0  2.0  1.0  0.0  0.0  0.0  0.0  0.0
1.0  1.0  2.0  2.0  0.0  0.0  0.0  0.0  0.0
1.0  1.0  2.0  3.0  0.0  0.0  0.0  0.0  0.0
1.0  1.0  3.0  0.0  0.0  0.0  0.0  0.0  0.0
1.0  1.0  3.0  1.0  0.0  0.0  0.0  0.0  0.0
1.0  1.0  3.0  2.0  0.0  0.0  0.0  0.0  0.0
1.0  1.0  3.0  3.0  0.0  0.0  0.0  0.0  0.0

其中Tmu1mu2mu3是我控制的变量的4个轴(自变量)。 abcde是我所做的测量(因变量)。

我想将这个2D数组转换为numpy中的5D数组。通过指定Tmu1mu2mu3(或至少其4个索引),我希望能够检索相应的a,{{ 1}},bcd值。

通过指定轴对应的列,有没有直接的方法来重塑这种数组? Pandas中的e似乎巧妙地将它组织在一张桌子中,但似乎不适合高维阵列。我不一定提前知道ndarray的形状应该是什么,但在我看来,基于这些值,应该可以正确地重塑阵列。每个轴的增量值也可能不同,但它们始终是一致的。

我目前的想法是忽略MultiIndexmu1mu2列,并将mu3数据集合堆叠到3D数组中。从那里我将3D T数据集合成一个4D数组,并使用mu1mu2重复该过程。这似乎是一个繁琐的过程,应该有一个简单的解决方案。

1 个答案:

答案 0 :(得分:1)

首先,让我们制作一些假数据:

# an N x 5 array containing a regular mesh representing the stimulus params
stim_params = np.mgrid[:2, :3, :4, :5, :6].reshape(5, -1).T

# an N x 3 array representing the output values for each simulation run
output_vals = np.arange(720 * 3).reshape(720, 3)

# shuffle the rows for a bit of added realism
shuf = np.random.permutation(stim_params.shape[0])
stim_params = stim_params[shuf]
output_vals = output_vals[shuf]

现在,您可以使用np.lexsort获取一组索引,这些索引将对2D模拟参数数组的行进行排序,以使每列中的值按升序排列。完成后,您可以将这些索引应用于模拟输出值的行。

# get the number of unique values for each stimulus parameter
params_shape = tuple(np.unique(col).shape[0] for col in stim_params.T)

# get the set of row indices that will sort the stimulus parameters in ascending
# order, starting with the final column
idx = np.lexsort(stim_params[:, ::-1].T)

# sort and reshape the stimulus parameters:
sorted_params = stim_params[idx].T.reshape((5,) + params_shape)

# sort and reshape the output values
sorted_output = output_vals[idx].T.reshape((3,) + params_shape)

我发现最困难的部分通常只是试图围绕输出的所有不同维度对应的内容:

# array of stimulus parameters, with dimensions (n_params, p1, p2, p3, p4, p5)
print(sorted_params.shape)
# (5, 2, 3, 4, 5, 6)

# to check that the sorting worked as expected, we can look at the values of the 
# 5th parameter when all the others are held constant at 0:
print(sorted_params[4, 0, 0, 0, 0, :])
# [0 1 2 3 4 5]

# ... and the 1st parameter when we hold all the others constant:
print(sorted_params[0, :, 0, 0, 0, 0])
# [0, 1]

# ... now let the 1st and 2nd parameters covary:
print(sorted_params[:2, :, :, 0, 0, 0])
# [[[0 0 0]
#   [1 1 1]]

#  [[0 1 2]
#   [0 1 2]]]

希望你明白了。相同的索引逻辑适用于排序的模拟输出:

# array of outputs, with dimensions (n_outputs, p1, p2, p3, p4, p5)
print(sorted_output.shape)
# (3, 2, 3, 4, 5, 6)

# the first output variable whilst holding the first 4 simulation parameters
# constant at 0:
print(sorted_output[0, 0, 0, 0, 0, :])
# [ 0  3  6  9 12 15]