在不改变尺寸的情况下更改多维NumPy阵列的形状

时间:2017-07-21 20:26:58

标签: python arrays numpy multidimensional-array

我目前正在修补Scikit-Learn函数,其中一行需要一个具有2维的NumPy数组。但是,我正在使用的数据是一个包含3个维度的NumPy数组,这会引发错误“解压缩的值太多。”

我正在调用K-Means函数fit来聚类数据。我的问题归结为以下一行代码,假设X是我传入的ndarray

n_samples, n_features = X.shape

X是一个包含3个维度的数组,如下所示:

X = np.array([[[1, 2, 3],
               [4, 5, 6]],

              [[7, 8, 9],
               [10, 11, 12]],

              [[13, 14, 15],
               [16, 17, 18]]])

数据表示一组具有6个维度的数据点的时间序列。例如,第一个元素[[1, 2, 3], [4, 5, 6]]表示一个时间序列,其中包含2个时间段的样本,每个样本都有3个维度。

我已对k_means_代码进行了修补,以允许我在ndarray ndarray上执行群集。我的目标是在2D阵列上执行k-means。

是否可以将3D ndarray的形状设置为2个元素?例如,我尝试将3D数组转换为2D对象数组,但最终会转换回3D数组。

np.array([[x.astype(object) for x in c] for c in combined])

同样,以下代码也会转换回3D数组。

np.array([[np.array(x) for x in c] for c in combined])

列表推导[[x.astype(object) for x in c] for c in combined]看起来像是创建了正确的数组,但由于它是类型列表,它不再适用于该函数。

我正在寻找将3D NumPy数组“转换”为2维的方法。任何帮助将不胜感激!

注意:我不是在寻找一种重塑数组的方法。我需要保留所有尺寸,但更改形状以忽略其中一个尺寸。

1 个答案:

答案 0 :(得分:1)

要制作一个数组数组,我们必须发挥一些技巧,因为np.array试图尽可能地创建一个高维数组。如果子阵列的大小不一样,但如果它们完全相同,我们就必须对抗它。

这是一种方式:

从3d数组开始:

In [812]: arr = np.arange(24).reshape(2,3,4)

和一个正确大小的空对象数组(但是展平)

In [813]: A = np.empty((6,),object)

复制值(再次使用展平),并重塑为目标形状

In [814]: A[:]=list(arr.reshape(-1,4))
In [815]: A=A.reshape(2,3)
In [816]: A
Out[816]: 
array([[array([0, 1, 2, 3]), array([4, 5, 6, 7]), array([ 8,  9, 10, 11])],
       [array([12, 13, 14, 15]), array([16, 17, 18, 19]),
        array([20, 21, 22, 23])]], dtype=object)

所以现在我们有一个(2,3)数组,其形状可以解压缩。

我尝试从np.empty((2,3),object)开始,但无法让A[:,:]=...作业完成。为了重塑这个对象,我们必须将arr拆分成一个数组列表。对象数组就像列表一样,是一个指针数组。

但是scikit函数会接受这样的数组吗? (通过形状障碍后)。我怀疑物体重塑是一个短视的解决方案。

In [824]: [[x.astype(object) for x in c] for c in arr]
Out[824]: 
[[array([0, 1, 2, 3], dtype=object),
  array([4, 5, 6, 7], dtype=object),
  array([8, 9, 10, 11], dtype=object)],
 [array([12, 13, 14, 15], dtype=object),
  array([16, 17, 18, 19], dtype=object),
  array([20, 21, 22, 23], dtype=object)]]
In [825]: _[0][0].shape
Out[825]: (4,)

这将创建一个嵌套的列表列表,内部元素为(4,)对象数组。将其包裹在np.array中,并使用dtype对象重新创建一个3d数组。

重塑,由于某种未知原因,您不想保留数字dtype

In [828]: arr.reshape(2,-1)
Out[828]: 
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]])
In [829]: arr.reshape(-1,4)
Out[829]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15],
       [16, 17, 18, 19],
       [20, 21, 22, 23]])