Ich baue Simulationssoftware, und ich muss (tausende) 2D-Numpy-Arrays in Tabellen in einer HDF5-Datei schreiben, wobei eine Dimension des Arrays variabel ist. Der eingehende ist vom Typ float32; Um Speicherplatz zu sparen, wird jedes Array als Tabelle mit entsprechenden Datentypen für die Spalten gespeichert (daher keine Arrays). Wenn ich Tabellen lese, möchte ich ein numpy.darray des Typs float32 abrufen, damit ich schöne Berechnungen für die Analyse machen kann. Unten ist ein Beispielcode mit einem Array mit den Spezies A, B und C plus Zeit.Numerische Arrays von und zu HDF5-Dateien lesen und schreiben
Die Art, wie ich gerade lese und schreibe, funktioniert ', aber es ist sehr langsam. Die Frage ist also: Was ist die geeignete Art, array
in table
schnell zu speichern und auch wieder in ndarrays einzulesen? Ich habe mit numpy.recarray experimentiert, aber ich kann das nicht zum Laufen bringen (Typfehler, Dimensionsfehler, völlig falsche Zahlen usw.)?
Code:
import tables as pt
import numpy as np
# Variable dimension
var_dim=100
# Example array, rows 0 and 3 should be stored as float32, rows 1 and 2 as uint16
array=(np.random.random((4, var_dim)) * 100).astype(dtype=np.float32)
filename='test.hdf5'
hdf=pt.open_file(filename=filename,mode='w')
group=hdf.create_group(hdf.root,"group")
particle={
'A':pt.Float32Col(),
'B':pt.UInt16Col(),
'C':pt.UInt16Col(),
'time':pt.Float32Col(),
}
dtypes=np.array([
np.float32,
np.uint16,
np.uint16,
np.float32
])
# This is the table to be stored in
table=hdf.create_table(group,'trajectory', description=particle, expectedrows=var_dim)
# My current way of storing
for i, row in enumerate(array.T):
table.append([tuple([t(x) for t, x in zip(dtypes, row)])])
table.flush()
hdf.close()
hdf=pt.open_file(filename=filename,mode='r')
array_table=hdf.root.group._f_iter_nodes().__next__()
# My current way of reading
row_list = []
for i, row in enumerate(array_table.read()):
row_list.append(np.array(list(row)))
#The retreived array
array=np.asarray(row_list).T
# I've tried something with a recarray
rec_array=array_table.read().view(type=np.recarray)
# This gives me errors, or wrong results
rec_array.view(dtype=np.float64)
hdf.close()
Der Fehler erhalte ich:
Traceback (most recent call last):
File "/home/thomas/anaconda3/lib/python3.6/site-packages/numpy/core/records.py", line 475, in __setattr__
ret = object.__setattr__(self, attr, val)
ValueError: new type not compatible with array.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/thomas/Documents/Thesis/SO.py", line 53, in <module>
rec_array.view(dtype=np.float64)
File "/home/thomas/anaconda3/lib/python3.6/site-packages/numpy/core/records.py", line 480, in __setattr__
raise exctype(value)
ValueError: new type not compatible with array.
Closing remaining open files:test.hdf5...done
Es könnte helfen, die Form und dtype von 'array' (von dem ersten sehen' asarray'). Ich vermute, es ist bereits ein strukturiertes Array. Oder die ähnlichen Informationen für die 'recarray' Version. – hpaulj
Ist die Verwendung von Tabellen die einzige Lösung, die für Sie möglich ist? Wie greifen Sie danach auf Ihre Daten zu (nur die ganzen 2D-Arrays oder Subsets davon)? – max9111
Gibt es auch nur wenige Spalten (in Ihrem Beispiel nur vier) in Ihren realen Daten? Sind Ihre Daten komprimierbar? Ist sogar eine verlustbehaftete Kompression eine Möglichkeit für Sie? https://computation.llnl.gov/projects/floating-point-compression/zfp-compression-ratio-and-quality – max9111