ndarray to structured_array and float to int



我遇到的问题是,使用ndarray.view(np.dtype)从经典ndarray获取结构化数组似乎计算错误了floatint的转换。

示例更有说服力:

In [12]: B
Out[12]: 
array([[  1.00000000e+00,   1.00000000e+00,   0.00000000e+00,
0.00000000e+00,   4.43600000e+01,   0.00000000e+00],
[  1.00000000e+00,   2.00000000e+00,   7.10000000e+00,
1.10000000e+00,   4.43600000e+01,   1.32110000e+02],
[  1.00000000e+00,   3.00000000e+00,   9.70000000e+00,
2.10000000e+00,   4.43600000e+01,   2.04660000e+02],
..., 
[  1.28900000e+03,   1.28700000e+03,   0.00000000e+00,
9.99999000e+05,   4.75600000e+01,   3.55374000e+03],
[  1.28900000e+03,   1.28800000e+03,   1.29000000e+01,
5.40000000e+00,   4.19200000e+01,   2.08400000e+02],
[  1.28900000e+03,   1.28900000e+03,   0.00000000e+00,
0.00000000e+00,   4.19200000e+01,   0.00000000e+00]])
In [14]: B.view(A.dtype)
Out[14]: 
array([(4607182418800017408, 4607182418800017408, 0.0, 0.0, 44.36, 0.0),
(4607182418800017408, 4611686018427387904, 7.1, 1.1, 44.36, 132.11),
(4607182418800017408, 4613937818241073152, 9.7, 2.1, 44.36, 204.66),
...,
(4653383897399164928, 4653375101306142720, 0.0, 999999.0, 47.56, 3553.74),
(4653383897399164928, 4653379499352653824, 12.9, 5.4, 41.92, 208.4),
(4653383897399164928, 4653383897399164928, 0.0, 0.0, 41.92, 0.0)], 
dtype=[('i', '<i8'), ('j', '<i8'), ('tnvtc', '<f8'), ('tvtc', '<f8'), ('tf', '<f8'), ('tvps', '<f8')])

"i"one_answers"j"列是真整数:

这里有我做的两次进一步检查,问题似乎来自ndarray.view(np.int)

In [21]: B[:,:2]
Out[21]: 
array([[  1.00000000e+00,   1.00000000e+00],
[  1.00000000e+00,   2.00000000e+00],
[  1.00000000e+00,   3.00000000e+00],
..., 
[  1.28900000e+03,   1.28700000e+03],
[  1.28900000e+03,   1.28800000e+03],
[  1.28900000e+03,   1.28900000e+03]])
In [22]: B[:,:2].view(np.int)
Out[22]: 
array([[4607182418800017408, 4607182418800017408],
[4607182418800017408, 4611686018427387904],
[4607182418800017408, 4613937818241073152],
..., 
[4653383897399164928, 4653375101306142720],
[4653383897399164928, 4653379499352653824],
[4653383897399164928, 4653383897399164928]])
In [23]: B[:,:2].astype(np.int)
Out[23]: 
array([[   1,    1],
[   1,    2],
[   1,    3],
..., 
[1289, 1287],
[1289, 1288],
[1289, 1289]])

我做错了什么?由于内存分配不足,我不能更改类型吗?有没有其他方法可以做到这一点(从数组中,指责shape mismatch

这是执行somearray.view(new_dtype)和调用astype的区别。

你所看到的正是预期的行为,这是非常深思熟虑的,但当你第一次遇到它时,它就是起义

具有不同数据类型的视图将数组的底层内存缓冲区解释为给定的数据类型。没有复制。它非常强大,但你必须明白自己在做什么。

需要记住的一点是,调用view永远不会改变底层内存缓冲区,只是numpy查看它的方式(例如dtype、shape、steps)。因此,view有意避免将数据更改为新类型,而只是将"旧位"解释为新的数据类型。

例如:

In [1]: import numpy as np
In [2]: x = np.arange(10)
In [3]: x
Out[3]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [4]: x.dtype
Out[4]: dtype('int64')
In [5]: x.view(np.int32)
Out[5]: array([0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0],
dtype=int32)
In [6]: x.view(np.float64)
Out[6]:
array([  0.00000000e+000,   4.94065646e-324,   9.88131292e-324,
1.48219694e-323,   1.97626258e-323,   2.47032823e-323,
2.96439388e-323,   3.45845952e-323,   3.95252517e-323,
4.44659081e-323])

如果要使用新的数据类型复制阵列,请使用astype

In [7]: x
Out[7]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [8]: x.astype(np.int32)
Out[8]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int32)
In [9]: x.astype(float)
Out[9]: array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.])

然而,将astype与结构化数组一起使用可能会让您大吃一惊。结构化数组将输入的每个元素视为类C结构。因此,如果你调用astype,你会遇到几个惊喜。


基本上,您希望列具有不同的数据类型。在这种情况下,不要将它们放在同一个数组中。Numpy数组应该是同质的。结构化数组在某些情况下很方便,但如果您正在寻找处理单独数据列的东西,它们可能不是您想要的。只需将每列用作自己的数组。

更好的是,如果您使用的是表格数据,您可能会发现使用pandas比直接使用numpy数组更容易。pandas面向表格数据(其中列应具有不同的类型),而numpy面向同质数组。

实际上,from_arrays是有效的,但它并不能解释这种奇怪的行为。

这是我找到的解决方案:

np.core.records.fromarrays(B.T, dtype=A.dtype)

在类似情况下对我有效的唯一解决方案:

np.array([tuple(row) for row in B], dtype=A.dtype)

最新更新