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

Python 将结构化数组转换为常规NumPy数组,python,numpy,recarray,Python,Numpy,Recarray,我想答案很明显,但我目前看不到 如何将记录数组转换回常规数据数组? 假设我有以下简单的结构化数组: x = np.array([(1.0, 4.0,), (2.0, -1.0)], dtype=[('f0', '<f8'), ('f1', '<f8')]) 我尝试了asarray和astype,但没有成功 更新(已解决:浮点32(f4)而不是浮点64(f8)) 好的,我尝试了Robert(x.view(np.float64))的解决方案。重塑(x.shape+(-1,)),通过一个

我想答案很明显,但我目前看不到

如何将记录数组转换回常规数据数组?

假设我有以下简单的结构化数组:

x = np.array([(1.0, 4.0,), (2.0, -1.0)], dtype=[('f0', '<f8'), ('f1', '<f8')])
我尝试了asarray和astype,但没有成功

更新(已解决:浮点32(f4)而不是浮点64(f8))

好的,我尝试了Robert(
x.view(np.float64))的解决方案。重塑(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')])
给出:

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]])
这是一个包含其他数字和其他形状的数组。我做错了什么

np.array(x.tolist())
array([[ 1.,  4.],
      [ 2., -1.]])
但是也许有更好的方法…

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

|5> x=np.array([(1.0,4.0,),(2.0,-1.0)],dtype=[('f0','最简单的方法可能是

x.view((float, len(x.dtype.names)))
float
通常必须替换为
x
中的元素类型:
x.dtype[0]
)。这假设所有元素都具有相同的类型


此方法在一个步骤中为您提供常规的
numpy.ndarray
版本(与
视图(…)所需的两个步骤相反)。重塑(…)
方法。

结合对其处理多字段索引方式的更改
numpy
提供了两个新功能,可帮助转换为结构化数组或从结构化数组转换为结构化数组:

numpy.lib.recfunctions
中,这些是
结构化到非结构化的
非结构化到结构化的
重新打包字段
是另一个新函数

1.16
发行说明

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

为具有多个字段的结构化数组编制索引(例如,arr[['f1',f3']])会将视图返回到原始数组中,而不是返回副本。与以前不同,返回的视图通常会有与原始数组中的中间字段相对应的额外填充字节,这将影响arr['f1',f3']]等代码。视图('float64')。此更改是从numpy 1.7开始计划的。从此以后,运行此路径的操作发出了未来警告。1.12中添加了有关此更改的其他未来警告

为了帮助用户更新代码以应对这些更改,在numpy.lib.recfunctions模块中添加了许多函数,这些函数可以安全地允许此类操作。例如,上面的代码可以替换为结构化的到非结构化的(arr[['f1',f3']],dtype='float64')。请参阅“访问多个字段”用户指南的第节


一个非常简单的解决方案,使用以下函数的函数rec2array

root\u numpy实际上已被弃用,但是rec2array代码仍然很有用(源代码):


np.asanyarray(x)将为每个列维护复杂的数据类型,其他np.array(x.tolist())需要用
data.dtype[0]替换
np.float
。请在最后发布解决方案,更新您的问题,以便让读者更清楚。谢谢!我想这不会复制数组?@joris:您的数组包含单精度(32位)浮点数。若要将同一内存重新解释为非结构化数组,请使用
.view(np.float32)
在上面的代码中。@joris,正确,它没有复制。它只是原始数组中内存顶部的一个视图。不需要元组构造:
restrape(x.shape+(-1,)
可以简化为
restrape(x.shape,-1)
。我更新了答案。@RobertKern:在
restrape中确实没有记录它()
documentation string。但是,它在官方文档中的许多地方都有使用,所以我认为它是非常正式的(例如,你可以找到许多
reformate(I,j,k)
at的实例)。我要求NumPy社区澄清这一点()。这很慢,因为您第一次将高效压缩的NumPy数组转换为常规Python列表。官方方法要快得多(请参见我的答案)。这是最容易记住的方法…令人惊讶的是没有
x.toArray()
method…不必制作python列表,它们的成本要高得多。这确实很慢,但是唯一可靠的答案。其他的不适合我(numpy 1.14.x)。此方法在结构化数组具有多个数据类型时有效,其他方法在这种情况下会失败。对于速度不重要的单元测试非常有用,只需比较即可。我将添加一个改进:
x.view((x.dtype[0],len(x.dtype.names)))
。因此,我们甚至可以定义一个函数来实现这一点,因为所有内容都是参数化的。您提到了烹饪书中有一些有效的方法。您介意指出它们的位置吗?我不知道如何找到它们。答案中的链接无效。我找不到它最初引用的页面。我一直在使用此方法有一段时间;不幸的是,现在我得到了“FutureWarning:Numpy检测到您可能正在查看或写入通过在结构化数组中选择多个字段返回的数组。此代码可能在Numpy 1.13中中断,因为这将返回一个视图而不是副本--有关详细信息,请参阅发行说明。”如何处理这个问题?这在Numpy 1.14中对我不起作用。假设我有以下结构化数组:
arr=np.array([(105.0,34.0,145.0,217.0)],dtype=[('a','f4'),('b','f4'),('c','f4'),('d','f4')])
。然后尝试通过
out=arr[0]将内部的4元组转换为常规数组。查看((np.float32,len(arr.dtype.names))
会导致
值错误:只有在itemsize保持不变的情况下才支持更改0d数组的数据类型。
下面是指向用户指南部分的链接。这是一个比所选答案更好的答案。使用
查看(float)
不允许提取和合并字段子集,而
结构化字段到非结构化字段
[~]
|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.]])
x.view((float, len(x.dtype.names)))
np_array = rec2array(x)
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