将结构化数组转换为常规NumPy数组

59 投票
5 回答
32601 浏览
提问于 2025-04-16 17:24

我觉得答案应该很明显,但我现在想不起来。

我该如何把一个记录数组转换回普通的ndarray?

假设我有一个简单的结构化数组:

x = np.array([(1.0, 4.0,), (2.0, -1.0)], dtype=[('f0', '<f8'), ('f1', '<f8')])

然后我想把它转换成:

array([[ 1.,  4.],
       [ 2., -1.]])

我试过用 asarrayastype,但都不行。

更新(解决了:用 float32 (f4) 而不是 float64 (f8))

好的,我试了罗伯特的解决方案(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]])

这是一个有不同数字和形状的数组。我到底哪里出错了?

5 个回答

18

随着对多字段索引处理方式的改变,numpy 提供了两个新功能,可以帮助我们在结构化数组和非结构化数组之间转换:

numpy.lib.recfunctions 模块中,这两个功能分别是 structured_to_unstructuredunstructured_to_structured。还有一个新功能叫 repack_fields

以下是 1.16 版本的更新说明:

多字段视图返回的是视图而不是副本。

当我们用多个字段索引一个结构化数组,比如 arr[['f1', 'f3']],返回的将是原始数组的视图,而不是副本。这个返回的视图通常会包含一些额外的填充字节,这些字节对应于原始数组中介于字段之间的部分,这和之前的情况不同,这会影响到像 arr[['f1', 'f3']].view('float64') 这样的代码。这个改变从 numpy 1.7 开始就已经计划好了。从那时起,涉及到这个路径的操作就会发出未来警告。1.12 版本中还增加了关于这个变化的额外未来警告。

为了帮助用户更新他们的代码以适应这些变化,numpy.lib.recfunctions 模块中添加了一些功能,可以安全地进行这些操作。例如,上面的代码可以用 structured_to_unstructured(arr[['f1', 'f3']], dtype='float64') 来替代。有关“访问多个字段”的更多信息,请参见用户指南中的相关部分。

49

最简单的方法可能是

x.view((float, len(x.dtype.names)))

float通常需要替换成中元素的类型:x.dtype[0])。这个方法假设所有元素都是同一种类型。

这个方法可以一步到位地得到常规的numpy.ndarray版本(而不是像view(…).reshape(…)那样需要两步)。

35

在编程中,有时候我们会遇到一些问题,特别是在使用某些工具或库的时候。这些问题可能会让我们感到困惑,尤其是当我们刚开始学习编程的时候。为了帮助大家更好地理解这些问题,很多人会在网上提问,比如在StackOverflow上。这里的讨论通常会涉及到一些具体的代码示例和解决方案,帮助大家找到答案。

在这些讨论中,大家会分享自己的经验,指出可能的错误,或者给出一些建议。这样一来,即使是编程小白也能从中学到很多东西,逐渐提高自己的技能。

总之,编程的学习过程就是不断地提问和解决问题的过程,大家可以通过交流和分享来共同进步。

[~]
|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.]])

撰写回答