Ich habe eine große Anzahl von Zahlen in einer CSV-Datei geschrieben und muss nur eine Scheibe dieses Arrays laden. Konzeptionell möchte ich np.genfromtxt()
aufrufen und dann das resultierende Array in Zeilen schneiden, aber
MATLAB hat die Funktion textscan()
, die einen Dateideskriptor aufnehmen und nur einen Teil der Datei lesen kann. Gibt es so etwas in NumPy?
Vorläufig habe ich die folgende Funktion definiert, die nur die Zeilen liest, die die gegebene Bedingung erfüllen:
%Vor%Es gibt mehrere Probleme mit dieser Lösung:
genfromtxt
die Typen erkennt, die von Spalte zu Spalte variieren können; auch fehlende Werte, Konverter, Überspringen usw.; Gibt es eine Standardfunktion, die das Filtern implementiert, oder ein Gegenstück zu MATLABs textscan
?
Ich kann mir zwei Ansätze vorstellen, die einige der gewünschten Funktionen bieten:
Eine Datei entweder in Blöcken / oder in Schritten von n-Zeilen / etc. lesen:
Sie können ein generator
an numpy.genfromtxt übergeben sowie numpy.loadtxt . Auf diese Weise können Sie ein großes Dataset aus einem Textdateispeicher effizient laden, während Sie all die praktischen Syntaxanalysefunktionen der beiden Funktionen beibehalten.
Daten nur aus Zeilen lesen, die einem Kriterium entsprechen, das als Regex ausgedrückt werden kann:
Sie können numpy.fromregex verwenden und regular expression
verwenden. zu genau definieren, welche Token von einer gegebenen Zeile in der Eingabedatei geladen werden sollen. Zeilen, die nicht mit dem Muster übereinstimmen, werden ignoriert.
Um die beiden Ansätze zu veranschaulichen, werde ich ein Beispiel aus meinem Forschungskontext verwenden.
Ich muss oft Dateien mit der folgenden Struktur laden:
Diese Dateien können riesig sein (GBs) und ich bin nur an den numerischen Daten interessiert. Alle Datenblöcke haben die gleiche Größe - 6
in diesem Beispiel - und sie sind immer durch zwei Zeilen getrennt. Das stride
der Blöcke ist also 8
.
Zuerst werde ich einen Generator definieren, der die unerwünschten Linien herausfiltert:
%Vor% Dann öffne ich die Datei, erstelle einen filter_lines
-generator (hier muss ich die stride
kennen) und übergebe diesen Generator an genfromtxt
:
Das funktioniert wie ein Kinderspiel. Beachten Sie, dass ich usecols
verwenden kann, um die erste Spalte der Daten loszuwerden. Auf die gleiche Weise könnten Sie alle anderen Funktionen von genfromtxt
verwenden, um die Typen zu erkennen, verschiedene Typen von Spalte zu Spalte, fehlende Werte, Konverter, etc.
In diesem Beispiel war data.shape
(204000, 3)
, während die ursprüngliche Datei aus 272000
lines bestand.
Hier wird die generator
verwendet, um homogen gestreckte Linien zu filtern, aber man kann sich auch vorstellen, dass sie inhomogene Linienblöcke nach (einfachen) Kriterien ausfiltert.
Hier ist die regexp
, die ich verwenden werde:
Gruppen - d. h. in ()
- definieren die Token, die aus einer gegebenen Zeile extrahiert werden sollen.
Als nächstes führt fromregex
den Job aus und ignoriert Zeilen, die nicht mit dem Muster übereinstimmen:
Das Ergebnis ist genau das gleiche wie beim ersten Ansatz.
Wenn Sie eine Liste von Typen übergeben (die Formatbedingung), einen try-Block verwenden und yield verwenden, um genfromtxt als Generator zu verwenden, sollten wir in der Lage sein, textscan()
zu replizieren.
Bearbeiten: Ich habe den Ausnahmeblock vergessen. Es läuft jetzt in Ordnung, und Sie können GenFormtext als Generator verwenden (mit einem zufälligen CSV-Protokoll, das ich herumgesessen habe):
%Vor% Ich sollte wahrscheinlich bemerken, dass ich zip
verwende, um die Komma-Trennlinie und das formatSpec zusammenzufassen, das die beiden Listen auflöst (stoppt, wenn eine der Listen keine Elemente mehr hat), so dass wir sie gemeinsam durchlaufen können , eine Schleife vermeiden, die von len(line)
oder etwas ähnlichem abhängt.
Tags und Links python numpy bigdata input large-files