将numpy的recarray
转换为普通数组的最佳方法是什么?
我可以先.tolist()
然后再做一次array()
,但这似乎效率不高..
示例:
import numpy as np
a = np.recarray((2,), dtype=[('x', int), ('y', float), ('z', int)])
>>> a
rec.array([(30408891, 9.2944097561804909e-296, 30261980),
(44512448, 4.5273310988985789e-300, 29979040)],
dtype=[('x', '<i4'), ('y', '<f8'), ('z', '<i4')])
>>> np.array(a.tolist())
array([[ 3.04088910e+007, 9.29440976e-296, 3.02619800e+007],
[ 4.45124480e+007, 4.52733110e-300, 2.99790400e+007]])
答案 0 :(得分:12)
通过“普通数组”,我认为它是指同质dtype的NumPy数组。给出一个重新组合,例如:
>>> a = np.array([(0, 1, 2),
(3, 4, 5)],[('x', int), ('y', float), ('z', int)]).view(np.recarray)
rec.array([(0, 1.0, 2), (3, 4.0, 5)],
dtype=[('x', '<i4'), ('y', '<f8'), ('z', '<i4')])
我们必须首先使每列具有相同的dtype。然后我们可以通过相同的dtype查看数据将其转换为“正常数组”:
>>> a.astype([('x', '<f8'), ('y', '<f8'), ('z', '<f8')]).view('<f8')
array([ 0., 1., 2., 3., 4., 5.])
astype返回一个新的numpy数组。因此,上述内容需要额外的内存,其数量与a
的大小成比例。每行a
需要4 + 8 + 4 = 16字节,而a.astype(...)
需要8 * 3 = 24字节。调用view不需要新内存,因为view
只会更改基础数据的解释方式。
a.tolist()
返回一个新的Python列表。每个Python编号都是一个对象,它需要比numpy数组中的等效表示更多的字节。因此a.tolist()
需要比a.astype(...)
更多的内存。
拨打a.astype(...).view(...)
的速度也快于np.array(a.tolist())
:
In [8]: a = np.array(zip(*[iter(xrange(300))]*3),[('x', int), ('y', float), ('z', int)]).view(np.recarray)
In [9]: %timeit a.astype([('x', '<f8'), ('y', '<f8'), ('z', '<f8')]).view('<f8')
10000 loops, best of 3: 165 us per loop
In [10]: %timeit np.array(a.tolist())
1000 loops, best of 3: 683 us per loop
答案 1 :(得分:0)
这是使用pandas
的相对干净的解决方案:
>>> import numpy as np
>>> import pandas as pd
>>> a = np.recarray((2,), dtype=[('x', int), ('y', float), ('z', int)])
>>> arr = pd.DataFrame(a).to_numpy()
>>> arr
array([[9.38925058e+013, 0.00000000e+000, 1.40380704e+014],
[1.40380704e+014, 6.93572751e-310, 1.40380484e+014]])
>>> arr.shape
(2, 3)
>>> arr.dtype
dtype('float64')
首先将recarray
中的数据加载到pd.DataFrame
中,然后使用DataFrame.to_numpy
方法将数据导出。如我们所见,该方法调用已自动将所有数据转换为类型float64
。