I have a structured numpy array.
The numpy structure matches the type google.protobuf.Timestamp
.
I need to extract the seconds
int64
and the nanos
int32
from each element of said structure and assign it to the real Timestamp
structure.
Below I list a script that does just that in a convenient way for anyone to test (numpy
and protobuf
Python modules need to be installed).
How do I get rid/circumvent the TypeError
listed at the end and have the values out of the numpy structure in the Timestamp
variable?
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("-----")
Disclaimer: hardcore newbie when it comes to python and numpy arrays.
So
I don't usually recommend using
nditer
unless you need special behavior. Simple iteration on the array (rows if 2d) is usually all you need. But to better understand what is happening, lets compare the iteration methods:Same except the
type
is different,np.ndarray
v.np.void
. It's easier to modify thenditer
variable.Do the same but looking at one field:
I don't have the
protobuf
code, but I suspectwill work better with the 2nd iteration, the one that produces
np.int64
values. Or addelem['seconds'].item()
.