子集影响.view(np.float64)行为

时间:2017-12-13 15:03:18

标签: python arrays numpy casting subset

我正在尝试使用一些sklearn估计器对一些快速傅里叶变换(技术上的离散傅里叶变换)的系数进行分类。我获得一个numpy数组X_c作为np.fft.fft(X)的输出,我想将它转换为一个真正的numpy数组X_r,原始X_c的每个(复杂)列转换为两个(实/浮)列X_r,即形状从(r,c)到(r,2c)。所以我使用.view(np.float64)。它最初起作用。

问题在于,如果我首先决定只用X_c2 = X_c [:,range(3)]保留原始复数数组的一些系数,然后再做与以前相同的事情而不是使列数加倍,我获得了加倍的排名数(每个元素的虚部放在原始的新行之下)。

我真的不明白为什么会这样。

为了让自己更清楚,这是一个玩具的例子:

import numpy as np

# I create a complex array
X_c = np.arange(8, dtype = np.complex128).reshape(2, 4)
print(X_c.shape) # -> (2, 4)

# I use .view to transform it into something real and it works
# the way I want it.
X_r = X_c.view(np.float64)
print(X_r.shape) # -> (2, 8)

# Now I subset the array.
indices_coef = range(3)
X_c2 = X_c[:, indices_coef]
print(X_c2.shape) # -> (2, 3)
X_r2 = X_c2.view(np.float64)

# In the next line I obtain (4, 3), when I was expecting (2, 6)...
print(X_r2.shape) # -> (4, 3)

有没有人看到这种行为差异的原因?

1 个答案:

答案 0 :(得分:0)

我收到警告:

In [5]: X_c2 = X_c[:,range(3)]
In [6]: X_c2
Out[6]: 
array([[ 0.+0.j,  1.+0.j,  2.+0.j],
       [ 4.+0.j,  5.+0.j,  6.+0.j]])
In [7]: X_c2.view(np.float64)
/usr/local/bin/ipython3:1: DeprecationWarning: Changing the shape of non-C contiguous array by
descriptor assignment is deprecated. To maintain
the Fortran contiguity of a multidimensional Fortran
array, use 'a.T.view(...).T' instead
  #!/usr/bin/python3
Out[7]: 
array([[ 0.,  1.,  2.],
       [ 0.,  0.,  0.],
       [ 4.,  5.,  6.],
       [ 0.,  0.,  0.]])


In [12]: X_c2.strides
Out[12]: (16, 32)
In [13]: X_c2.flags
Out[13]: 
  C_CONTIGUOUS : False
  F_CONTIGUOUS : True

那么这个副本(或者是一个视图?)是Fortran命令。建议的X_c2.T.view(float).T生成相同的4x3阵列而没有警告。

如您的第一个视图所示,复杂数组的数据布局与浮点数的两倍相同。

在尝试view结构化数组时,我看到了有趣的形状行为。我想知道complex dtype的行为与dtype('f8,f8')数组非常相似。

如果我更改了您的X_c2,那么它就是副本,我会得到预期的行为

In [19]: X_c3 = X_c[:,range(3)].copy()
In [20]: X_c3.flags
Out[20]: 
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False
In [21]: X_c3.strides
Out[21]: (48, 16)
In [22]: X_c3.view(float)
Out[22]: 
array([[ 0.,  0.,  1.,  0.,  2.,  0.],
       [ 4.,  0.,  5.,  0.,  6.,  0.]])

令人放心。但我很困惑为什么[:, range(3)]索引会创建F订单视图。那应该是提前索引。

事实上,真正的切片不允许这种观点

In [28]: X_c[:,:3].view(np.float64)
---------------------------------------------------------------------------
ValueError: new type not compatible with array.

因此范围索引创建了某种混合对象。