Lesen mehrere JSON-Datensätze in ein Pandas dataframe
Ich würde gerne wissen, ob es eine Speicher-effiziente Art des Lesens multi record JSON-Datei ( jede Zeile ist ein JSON-dict) in ein pandas dataframe. Unten ist eine 2-Zeile B. mit der Lösung arbeiten, ich brauche es für eine potentiell sehr große Anzahl von Datensätzen. Beispiel für die Verwendung wäre die Prozess-Ausgangsdaten von Hadoop Pig JSonStorage Funktion.
import json
import pandas as pd
test='''{"a":1,"b":2}
{"a":3,"b":4}'''
#df=pd.read_json(test,orient='records') doesn't work, expects []
l=[ json.loads(l) for l in test.splitlines()]
df=pd.DataFrame(l)
- Verwenden Sie die chunksize-Attribut von pd.read_json, um eine Liste von dataframes und mit map oder Schleife zur Iteration über die dataframes
Du musst angemeldet sein, um einen Kommentar abzugeben.
Hinweis: Zeile getrennt json wird unterstützt-in
read_json
(seit 0.19.0):oder mit einer Datei/Dateipfad anstatt eines json-Strings:
Es wird abhängig von der Größe der Sie DataFrames, welche schneller ist, aber eine andere Möglichkeit ist die Verwendung
str.join
zu zerschlagen, Ihre multi-line "JSON" (Anmerkung: es ist nicht gültiges json), in Gültiger json und verwenden read_json:Für dieses kleine Beispiel ist dies langsamer, wenn rund 100 es ist dem ähnlich, erhebliche Gewinne, wenn es größer...
Hinweis: die Verknüpfung ist überraschend schnell.
data = pd.read_json('/path/to/file.json', lines=True)
dfs = pd.read_json('file', lines=True, chunksize=x)
undfor df in dfs: df.head()
Wenn Sie versuchen, um Speicher zu sparen, dann das Lesen der Datei eine Zeile zu einem Zeitpunkt viel mehr Speicher effizient:
Auch, wenn Sie
import simplejson as json
, die den kompilierten C-Erweiterungen enthalten, die mitsimplejson
sind viel schneller als die pure-Pythonjson
Modul.DataFrame
Konstruktor. Und aktuelle Versionen von Python enthalten kompilierten C-Erweiterungen für die eingebautejson
. Zum Glück, wie der Pandas 0.19, können Sieread_json(lines=True)
.l=[ json.loads(l) for l in test.splitlines()]
, die Bedürfnisse zu haben, in Erinnerung, alle auf einmal: 1. Der komplette Orginal-Datei Daten, 2. Die Datei-Daten-Aufteilung in Zeilen (gelöscht, sobald alle Linien analysiert), und 3. Die geparsten JSON-Objekte. Lesen träge und be-Zeile heißt, Sie haben nur #3 von den oben genannten, plus ein (technisch gesehen zwei, aber logisch eins) Zeile der Datei im Speicher auf einmal. Sicher, alle der analysierten Objekte im Speicher, aber nicht zwei zusätzliche Kopien der Datei zu starten.list
zu den iterator. Es ist völlig gleichwertig.test.splitlines()
(Bedeutungtest
und dielist
der resultierenden Linien werden alle im Speicher gehalten, während dielist
gebaut wird), während der Doctor J ist iterierbar istf
(ein open-file-Objekt), die zieht jeder Zeile, wie es geht, ersetzen Sie es sofort nach jedemjson.loads
.pd.DataFrame(json.loads(line) for line in f)
undpd.DataFrame([json.loads(line) for line in f])
würde entspricht (ehemaligelist
freundlich vonDataFrame
, letztere machtlist
direkt), aber die Datei vs.str.split
unterscheidet.list
von geparsten JSON-Objekte (plus die Größe der beiden größten Zeilen in der Datei), nicht dielist
von JSON-Objekten, sowie die komplette Datei-Inhalt, plus der komplette Inhalt der Datei wieder (aufgeteilt in Zeilen).list
vondict
s obwohl, die Kombination dieser Ansatz w/collections.namedtuple
.Row = namedtuple('Row', ('a', 'b'))
, dann ersetzen Sie die definition vondata
mitdata = pd.DataFrame(Row(**json.loads(line)) for line in f)
. Nun, anstelle von #Zeilendict
s, Sie haben #ZeilenRow
s, die laufen (auf meinem system) 64 Byte overhead jede, eher als 240, etwa 1/4 der Speicher-overhead.namedtuple
Ansatz erfordert, dass alle JSON-Objekte haben die gleichen Attribute (oder komplexe Ansätze liefern die Standardwerte für optionale Werte verwendet werden), es ist also nicht geeignet, um alle Umstände, aber die Provisorien sind viel weniger Schwergewicht auf diese Weise.Als der Pandas 0.19,
read_json
hat native Unterstützung für line-getrennte JSON:++++++++Update++++++++++++++
Als von v0.19, Pandas unterstützt das nativ (siehe https://github.com/pandas-dev/pandas/pull/13351). Führen Sie einfach:
++++++++Alte Antwort++++++++++
Den vorhandenen Antworten sind gut, aber für ein wenig Abwechslung, hier ist ein weiterer Weg, um Ihr Ziel zu erreichen, erfordert eine einfache pre-processing-Schritt außerhalb von python, so dass
pd.read_json()
verbrauchen können Daten.cat test.json | jq -c --slurp . > valid_test.json
df=pd.read_json('valid_test.json')
In ipython notebook, und führen Sie den shell-Befehl direkt aus der Zelle-Schnittstelle mit