#python #numpy #memory #floating-point #unsigned-integer
#python #numpy #память #с плавающей запятой #целое число без знака
Вопрос:
Я считываю данные датчика, которые содержат 6 столбцов, первые четыре из которых представляют собой 32-разрядные числа с плавающей запятой, а последние два — целые числа без знака. Вот как это преобразуется в массив numpy:
data = np.frombuffer(sensor_data.raw_data, dtype=np.dtype('float32')).reshape([-1, 6])
data = data[:, :5]
int_data = np.frombuffer(sensor_data.raw_data, dtype=np.dtype('uint')).reshape([-1, 6])
int_data = int_data[:, 4:6]
Это не кажется наиболее эффективным способом сделать это. Есть ли способ либо прочитать несколько типов данных, либо скрыть последние два столбца из float32
обратно в байты, а затем в uint
?
Комментарии:
1. Было бы проще создать правильное решение, если вы явно укажете, сколько байт использует каждое целое число без знака в файле.
np.dtype('uint')
может составлять 4 байта на некоторых платформах и 8 байт на других.
Ответ №1:
Если ваши 2 загрузки работают, беззнаковые целые числа должны быть 32-разрядными.
Мы можем построить эквивалентный структурированный массив с составным dtype:
In [58]: dt = np.dtype([('f0','f4',4),('f1','uint32',2)])
In [59]: arr = np.zeros(5, dt)
In [60]: arr['f0'] = np.random.rand(5,4)
In [61]: arr['f1'] = np.random.randint(0,100,(5,2))
In [62]: arr
Out[62]:
array([([0.38565257, 0.36662674, 0.5530039 , 0.17866635], [39, 3]),
([0.12109676, 0.60092086, 0.6555444 , 0.06968965], [18, 96]),
([0.7082187 , 0.48962796, 0.4019332 , 0.19190358], [26, 81]),
([0.34053752, 0.35870123, 0.22802468, 0.33509415], [48, 52]),
([0.45730132, 0.38697603, 0.18952931, 0.90458447], [ 3, 40])],
dtype=[('f0', '<f4', (4,)), ('f1', '<u4', (2,))])
и создайте буфер данных:
In [63]: astr = arr.tobytes()
Ваши нагрузки работают с этим буфером:
In [64]: data = np.frombuffer(astr, 'float32').reshape(-1,6)
In [65]: data[:,:4]
Out[65]:
array([[0.38565257, 0.36662674, 0.5530039 , 0.17866635],
[0.12109676, 0.60092086, 0.6555444 , 0.06968965],
[0.7082187 , 0.48962796, 0.4019332 , 0.19190358],
[0.34053752, 0.35870123, 0.22802468, 0.33509415],
[0.45730132, 0.38697603, 0.18952931, 0.90458447]], dtype=float32)
In [66]: data = np.frombuffer(astr, 'uint32').reshape(-1,6)
In [67]: data[:,4:]
Out[67]:
array([[39, 3],
[18, 96],
[26, 81],
[48, 52],
[ 3, 40]], dtype=uint32)
Но мы также можем использовать составной dtype для его загрузки:
In [68]: data = np.frombuffer(astr, dt)
In [69]: data['f0']
Out[69]:
array([[0.38565257, 0.36662674, 0.5530039 , 0.17866635],
[0.12109676, 0.60092086, 0.6555444 , 0.06968965],
[0.7082187 , 0.48962796, 0.4019332 , 0.19190358],
[0.34053752, 0.35870123, 0.22802468, 0.33509415],
[0.45730132, 0.38697603, 0.18952931, 0.90458447]], dtype=float32)
In [70]: data['f1']
Out[70]:
array([[39, 3],
[18, 96],
[26, 81],
[48, 52],
[ 3, 40]], dtype=uint32)
Этот составной dtype также будет работать с ‘uint64’.
Мы также могли бы получить uint32
из float32
загрузки, используя view
In [84]: data = np.frombuffer(astr, 'float32').reshape(-1,6)
In [86]: data[:,4:].view('uint32')
Out[86]:
array([[39, 3],
[18, 96],
[26, 81],
[48, 52],
[ 3, 40]], dtype=uint32)
(или значение float из uint с представлением)