[英]Extract python 'native' values from numpy structured array
我有一个结构化的numpy数组。
numpy结构与google.protobuf.Timestamp
类型google.protobuf.Timestamp
。
我需要从所述结构的每个元素中提取seconds
int64
和nanos
int32
并将其分配给实际的 Timestamp
结构。
下面,我列出了一个脚本,该脚本以一种方便所有人的方式方便地进行测试(需要安装numpy
和protobuf
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.