繁体   English   中英

从numpy结构化数组中提取python'native'值

[英]Extract python 'native' values from numpy structured array

我有一个结构化的numpy数组。

numpy结构与google.protobuf.Timestamp类型google.protobuf.Timestamp

我需要从所述结构的每个元素中提取seconds int64nanos int32并将其分配给实际的 Timestamp结构。

下面,我列出了一个脚本,该脚本以一种方便所有人的方式方便地进行测试(需要安装numpyprotobuf Python模块)。

如何摆脱/规避最后列出的TypeError ,并使值不在Timestamp变量的numpy结构之外?

import numpy as np
from google.protobuf import timestamp_pb2

# numpy structure that mimics google.protobuf.Timestamp
Timestamp_t = np.dtype([('seconds', np.int64), ('nanos', np.int32)])

# populate numpy array with above structure
x_values_size = 3
x_values = np.empty((x_values_size,), dtype=Timestamp_t)
x_values['seconds'] = np.linspace(0, 100, num=x_values_size, dtype=np.int64)
x_values['nanos']   = np.linspace(0, 10, num=x_values_size, dtype=np.int32)

# copy data from numpy structured array to a descriptor-created Timestamp
for elem in np.nditer(x_values) :
    # destination protobuf structure (actually, part of some sequence)
    # try 1: this will actually change the type of 'ts'
    ts1 = timestamp_pb2.Timestamp()
    print(type(ts1)) # Timestamp as expected
    ts1 = elem
    print(ts1) # now a numpy.ndarray
    print(type(ts1))
    print(ts1.dtype)

    # try 2: assign member by member
    ts2 = timestamp_pb2.Timestamp()
    # fails with:
    # TypeError: array(0, dtype=int64) has type <class 'numpy.ndarray'>, but expected one of: (<class 'int'>,)
    ts2.seconds = elem['seconds']
    ts2.nanos = elem['nanos']
    print("-----")

免责声明:涉及python和numpy数组的铁杆新手。

所以

In [112]: x_values
Out[112]: 
array([(  0,  0), ( 50,  5), (100, 10)], 
      dtype=[('seconds', '<i8'), ('nanos', '<i4')])

除非您需要特殊行为,否则我通常不建议使用nditer 通常只需要对数组进行简单迭代(如果为2d,则为行)。 但是为了更好地了解正在发生的事情,让我们比较一下迭代方法:

In [114]: for elem in np.nditer(x_values):
     ...:     print(elem, elem.dtype)
     ...:     print(type(elem))   
(0, 0) [('seconds', '<i8'), ('nanos', '<i4')]
<class 'numpy.ndarray'>
(50, 5) [('seconds', '<i8'), ('nanos', '<i4')]
<class 'numpy.ndarray'>
(100, 10) [('seconds', '<i8'), ('nanos', '<i4')]
<class 'numpy.ndarray'>

In [115]: for elem in x_values:
     ...:     print(elem, elem.dtype)
     ...:     print(type(elem))
(0, 0) [('seconds', '<i8'), ('nanos', '<i4')]
<class 'numpy.void'>
(50, 5) [('seconds', '<i8'), ('nanos', '<i4')]
<class 'numpy.void'>
(100, 10) [('seconds', '<i8'), ('nanos', '<i4')]
<class 'numpy.void'>

相同,除了type不同之外, np.ndarray np.void 修改nditer变量更容易。

做同样的事情,但只看一个领域:

In [119]: for elem in np.nditer(x_values):
     ...:     print(elem['seconds'], type(elem['seconds']))   
0 <class 'numpy.ndarray'>
50 <class 'numpy.ndarray'>
100 <class 'numpy.ndarray'>

In [120]: for elem in x_values:
     ...:     print(elem['seconds'], type(elem['seconds']))
0 <class 'numpy.int64'>
50 <class 'numpy.int64'>
100 <class 'numpy.int64'>

我没有protobuf代码,但我怀疑

ts2.seconds = elem['seconds']

与第二个迭代(生成np.int64值的迭代)一起使用会更好。 或添加elem['seconds'].item()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM