numpy: Zeilenweise CSV in Structured Array füllen

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
p90
User
Beiträge: 198
Registriert: Donnerstag 22. Juli 2010, 17:30

Hi,

habe ein Analyseprogramm, dass Daten aus tar Dateien Gewisse Werte (z.B. das Maximum eines Pulses) extrahiert.
Dazu habe ich bisher immer alle Dateien in einer Tar Datei gelesen und die Werte in eienr Liste zwischengespeichert.
Sobald ich alle Dateien durch hatte, wurde mit dieser Liste ein numpy structured array erzeugt mir dem danach weitergearbeitet wird.
Das sah bisher so aus:

Code: Alles auswählen

def calculate_data_matrix(data_iterator, bin2time):
    results = []
    for (identifier, nparray) in data_iterator:
        tmp = [float(i[1]) if "." in i[1] else int(i[1]) for i in identifier]
        try:
            data = analyze_nparray(nparray, bin2time)
            tmp.extend(data)
        except Exception as E:
            #show_y(nparray)
            print(identifier)
            print(E)
            print(traceback.format_exc())
            input("Error")
        #(x, y) = generate_pulse_anaylsis_plots(bin2time, nparray, tmp, plots = False)
        #tmp = analyze_nparray(digital_value, y, bin2time)
        results.append(tuple(tmp))
    dtype_base = [
            ("baseline", numpy.float64),
            ("max", numpy.float64),
            ("max_position", numpy.float64),
            ("raise_start", numpy.float64),
            ("raise_stop", numpy.float64),
            ("fall_start", numpy.float64),
            ("fall_stop", numpy.float64),
            ("fwhm_start", numpy.float64),
            ("fwhm_stop", numpy.float64),
            #("whittaker", numpy.object),
            ("raise_time", numpy.float64),
            ("fall_time", numpy.float64),
            ("fwhm", numpy.float64)]
    dtype_identifier = [(i[0], numpy.float64 if "." in i[1] else numpy.uint16) for i in identifier]
    dtype_identifier.extend(dtype_base)
    data_matrix = numpy.array(results,
        dtype=numpy.dtype(dtype_identifier))
    return data_matrix
Problem:
Meine Tar Dateien enthalten mittlerweile so viele Daten, dass ich diese Liste nicht mehr im Ram ablegen kann weil zu groß ^^.
Um das Problem zu umgehen wollte ich nun diese Funktion so umschreiben, dass ich zuerst einen structured array mit memmap
erzeuge und diesen dann Zeilenweise fülle.

Um dies zu testen habe ich ein kleines Programm geschrieben, dass zuerst alle Werte in einer CSV Datei zwischenspeichert,
dann die CSV Datei Zeilenweise einliest und die Werte an der Entsprechenden Stell in den memmapted structured array schreibt.

Das sieht so aus:

Code: Alles auswählen

import os
import csv
from file_helpers import get_bin2time_and_iterator
from analyzer_functions import analyze_nparray
import numpy

#erzeugung der csv datei
i = 0
with open(os.path.join("./cache", "all_data.csv"), 'w', newline='') as csvfile:
    csvwriter = csv.writer(csvfile, delimiter=' ', quotechar='|', quoting=csv.QUOTE_MINIMAL)
    for root, dirs, files in os.walk("./data", topdown=False):
        for file in files:
            print(file)
            if file.lower().endswith(".tar.xz"):
                (bin2time, data_iter) = get_bin2time_and_iterator(os.path.join(root, file))
                for (identifier, nparray) in data_iter:
                    tmp = [float(i[1]) if "." in i[1] else int(i[1]) for i in identifier]
                    data = analyze_nparray(nparray, bin2time)
                    tmp.extend(data)
                    csvwriter.writerow(tmp)
                    i += 1

dtype_base = [
            ("baseline", numpy.float64),
            ("max", numpy.float64),
            ("max_position", numpy.float64),
            ("raise_start", numpy.float64),
            ("raise_stop", numpy.float64),
            ("fall_start", numpy.float64),
            ("fall_stop", numpy.float64),
            ("fwhm_start", numpy.float64),
            ("fwhm_stop", numpy.float64),
            #("whittaker", numpy.object),
            ("raise_time", numpy.float64),
            ("fall_time", numpy.float64),
            ("fwhm", numpy.float64)]
dtype_identifier = [(i[0], numpy.float64 if "." in i[1] else numpy.uint16) for i in identifier]
dtypes = numpy.dtype(dtype_identifier)
data_matrix = numpy.memmap(os.path.join("./cache", "all_data.tmp"), dtype=dtypes, mode='w+', shape=(i,))

access_list = [j[0] for j in dtype_identifier]

i = 0
with open(os.path.join("./cache", "all_data.csv"), 'r', newline='') as csvfile:
    csvreader = csv.reader(csvfile, delimiter=' ', quotechar='|', quoting=csv.QUOTE_MINIMAL)
    for row in csvreader:
        #hier liegt das Problem
        data_matrix[i,:] = numpy.array([row], dtype=dtypes)
        i += 1
Die Erzeugung der CSV-Datei Funktioniert auch super, nur bekomme ich es einfach nicht hin, die Daten in den Structured Array zu laden.
Der Fehler den ich immer bekomme ist:

Code: Alles auswählen

Traceback (most recent call last):
  File "all_data_to_csv.py", line 55, in <module>
    data_matrix[i,:] = numpy.array([row], dtype=dtypes
TypeError: expected an object with a buffer interface
Ich vermute mal, dass ich das array irgendwie Falsch erzeuge. Ich verstehe nur nicht was ich falsch mache.
Für Tipps und Anmerkungen wäre ich sehr verbunden!

p90

PS:
Nein, hdf5 oder pytables ist leider keine Lösung ;) . Bekomme ich von "oben" verboten + müsste ich sehr viel in meiner Analyse umschreiben.
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Warum es schwierig ist Dir zu helfen:
  1. Du hast viel Code gepostet.
  2. Der Code ist nicht lauffähig (weil unvollständig).
  3. Du kennst die geeignete Lösung, sagst aber gleich, dass diese nicht in Frage kommt.
An Punkt 3 kannst Du wohl nichts ändern. Das ganze ohne Hdf5 zu realisieren wird die Kosten aber ordentlich nach oben treiben, bei gleichzeitig deutlich geringerer Leistung (Performance, Portierbarkeit, Skallierbarkeit, Dokumentation).

An Punkt 1 und 2 kannst Du aber was ändern. Fang erstmal mit einem file-maped Array mit weniger Spalten an. Bei diesem Beispiel sollte der Zusammengesetzte dtype nicht über mehrere Zeilen und mit einer Schleife konstruiert werden, sondern einfach explizit hingeschrieben werden. Schreibe dort ein paar von Dir selbst generierte Testdaten rein und schau ob es tut. Nimm für die Testdaten nicht die Random-Funktion, sondern eher sowas wie Sinus, dann kannst Du nachher einfacher testen, ob die Datei die reingeschriebenen Daten enthält.
a fool with a tool is still a fool, www.magben.de, YouTube
p90
User
Beiträge: 198
Registriert: Donnerstag 22. Juli 2010, 17:30

Hi,

erstmal Entschuldigung wegen der langen Zeit bis zu meiner Antwort.

@MagBen:
Du hast in allen Punkten recht, ich hätte es noch weiter eindampfen müssen.

Ich habe den Fehler mittlerweile den Fehler gefunden.
Man kann bei numpy structured arrays direkt tupeln für die Zuweisung verwenden.
Das Umformatieren mit dem Array ist nicht notwendig.

Wichtig, es muss eine Tuple sein, Listen gehen nicht.

euch allen einen schönen Gruß,

p90
Antworten