将结构化数组转换为常规 NumPy 数组
- 2025-03-20 08:47:00
- admin 原创
- 42
问题描述:
我认为答案会非常明显,但目前我还没有看到。
如何将记录数组转换回常规 ndarray?
假设我有以下简单的结构化数组:
x = np.array([(1.0, 4.0,), (2.0, -1.0)], dtype=[('f0', '<f8'), ('f1', '<f8')])
然后我想将其转换为:
array([[ 1., 4.],
[ 2., -1.]])
我尝试过asarray
和astype
,但是没有作用。
更新(已解决:float32(f4)而不是float64(f8))
好的,我尝试了 Robert () 的解决方案x.view(np.float64).reshape(x.shape + (-1,))
,使用简单的数组时,它运行完美。但对于我想要转换的数组,它给出了一个奇怪的结果:
data = np.array([ (0.014793682843446732, 0.006681123282760382, 0.0, 0.0, 0.0, 0.0008984912419691682, 0.0, 0.013475529849529266, 0.0, 0.0),
(0.014793682843446732, 0.006681123282760382, 0.0, 0.0, 0.0, 0.0008984912419691682, 0.0, 0.013475529849529266, 0.0, 0.0),
(0.014776384457945824, 0.006656022742390633, 0.0, 0.0, 0.0, 0.0008901208057068288, 0.0, 0.013350814580917358, 0.0, 0.0),
(0.011928378604352474, 0.002819152781739831, 0.0, 0.0, 0.0, 0.0012627150863409042, 0.0, 0.018906937912106514, 0.0, 0.0),
(0.011928378604352474, 0.002819152781739831, 0.0, 0.0, 0.0, 0.001259754877537489, 0.0, 0.01886274479329586, 0.0, 0.0),
(0.011969991959631443, 0.0028706740122288465, 0.0, 0.0, 0.0, 0.0007433745195157826, 0.0, 0.011164642870426178, 0.0, 0.0)],
dtype=[('a_soil', '<f4'), ('b_soil', '<f4'), ('Ea_V', '<f4'), ('Kcc', '<f4'), ('Koc', '<f4'), ('Lmax', '<f4'), ('malfarquhar', '<f4'), ('MRN', '<f4'), ('TCc', '<f4'), ('Vcmax_3', '<f4')])
进而:
data_array = data.view(np.float).reshape(data.shape + (-1,))
给出:
In [8]: data_array
Out[8]:
array([[ 2.28080997e-20, 0.00000000e+00, 2.78023241e-27,
6.24133580e-18, 0.00000000e+00],
[ 2.28080997e-20, 0.00000000e+00, 2.78023241e-27,
6.24133580e-18, 0.00000000e+00],
[ 2.21114197e-20, 0.00000000e+00, 2.55866881e-27,
5.79825816e-18, 0.00000000e+00],
[ 2.04776835e-23, 0.00000000e+00, 3.47457730e-26,
9.32782857e-17, 0.00000000e+00],
[ 2.04776835e-23, 0.00000000e+00, 3.41189244e-26,
9.20222417e-17, 0.00000000e+00],
[ 2.32706550e-23, 0.00000000e+00, 4.76375305e-28,
1.24257748e-18, 0.00000000e+00]])
这是一个包含其他数字和另一种形状的数组。我做错了什么?
解决方案 1:
最简单的方法可能是
x.view((float, len(x.dtype.names)))
(通常必须替换为:float
中元素的类型。这假定所有元素都具有相同的类型。x
`x.dtype[0]`
此方法只需一步即可提供常规numpy.ndarray
版本(与该方法所需的两个步骤相反view(…).reshape(…)
)。
解决方案 2:
[~]
|5> x = np.array([(1.0, 4.0,), (2.0, -1.0)], dtype=[('f0', '<f8'), ('f1', '<f8')])
[~]
|6> x.view(np.float64).reshape(x.shape + (-1,))
array([[ 1., 4.],
[ 2., -1.]])
解决方案 3:
结合处理多字段索引方式的变化,numpy
提供了两个可帮助转换为/从结构化数组的新功能:
在 中numpy.lib.recfunctions
,这些是structured_to_unstructured
和unstructured_to_structured
。 repack_fields
是另一个新功能。
来自1.16
发行说明
多字段视图返回视图而不是副本
对具有多个字段的结构化数组进行索引,例如 arr[['f1', 'f3']],将返回原始数组中的视图而不是副本。与之前不同,返回的视图通常会具有与原始数组中的中间字段相对应的额外填充字节,这会影响诸如 arr[['f1', 'f3']].view('float64') 之类的代码。此更改自 numpy 1.7 开始计划。从那时起,命中此路径的操作就会发出 FutureWarnings。有关此更改的其他 FutureWarnings 已添加到 1.12 中。
为了帮助用户更新代码以适应这些变化,numpy.lib.recfunctions 模块中添加了许多函数,可以安全地允许此类操作。例如,上面的代码可以替换为 structured_to_unstructured(arr[['f1', 'f3']], dtype='float64')。请参阅用户指南的“访问多个字段”部分。
解决方案 4:
np.array(x.tolist())
array([[ 1., 4.],
[ 2., -1.]])
但也许有更好的方法......
解决方案 5:
使用root_numpy的rec2array函数的一个非常简单的解决方案:
np_array = rec2array(x)
root_numpy实际上已被弃用,但rec2array 代码仍然有用(来源此处):
def rec2array(rec, fields=None):
simplify = False
if fields is None:
fields = rec.dtype.names
elif isinstance(fields, string_types):
fields = [fields]
simplify = True
# Creates a copy and casts all data to the same type
arr = np.dstack([rec[field] for field in fields])
# Check for array-type fields. If none, then remove outer dimension.
# Only need to check first field since np.dstack will anyway raise an
# exception if the shapes don't match
# np.dstack will also fail if fields is an empty list
if not rec.dtype[fields[0]].shape:
arr = arr[0]
if simplify:
# remove last dimension (will be of size 1)
arr = arr.reshape(arr.shape[:-1])
return arr
扫码咨询,免费领取项目管理大礼包!