2017-01-13 5 views
5

Hierbei geht es nicht um das Lesen großer JSON-Dateien, sondern darum, eine große Anzahl von JSON-Dateien möglichst effizient zu lesen.Eine große Anzahl von JSON-Dateien in Python lesen?

Frage

ich mit last.fm-Datensatz aus dem Million song dataset arbeite. Die Daten sind als Satz von JSON-codierten Textdateien verfügbar, in denen die Schlüssel sind: track_id, artist, title, timestamp, similars und tags.

Zur Zeit sie in Pandas in der folgenden Art und Weise lese ich, nachdem sie durch ein paar Optionen gehen, wie dies die schnellste wie gezeigt here ist:

import os 
import pandas as pd 
try: 
    import ujson as json 
except ImportError: 
    try: 
     import simplejson as json 
    except ImportError: 
     import json 


# Path to the dataset 
path = "../lastfm_train/" 

# Getting list of all json files in dataset 
all_files = [os.path.join(root,file) for root, dirs, files in os.walk(path) for file in files if file.endswith('.json')] 

data_list=[json.load(open(file)) for file in all_files] 
df = pd.DataFrame(data_list, columns=['similars', 'track_id']) 
df.set_index('track_id', inplace=True) 

Die aktuelle Methode liest die Teilmenge (1% des gesamten Datensatz in weniger als einer Sekunde). Das Lesen des ganzen Zuges ist jedoch zu langsam und dauert ewig (ich habe einige Stunden gewartet) und ist zu einem Flaschenhals für weitere Aufgaben geworden, wie sie in question here gezeigt werden.

Ich verwende auch ujson für Geschwindigkeitszwecke in json Dateien Parsen, die offenbar gesehen werden kann von this question here

UPDATE 1 Generator Verständnis anstelle von Liste Verständnis.

data_list=(json.load(open(file)) for file in all_files) 
+2

Es klingt wie Sie nicht genug RAM haben, und es beginnt, SWAP zu verwenden, die einfachste Lösung wäre, mehr RAM zu bekommen. –

+0

@FranciscoCouzo Einfachste vielleicht .. aber definitiv nicht das billigste! : D – dizzyf

+0

Ich habe schon 16Gigs davon und ich denke das ist definitiv genug um einen normalen Datensatz wie diesen zu lesen. Gibt es eine bessere Möglichkeit, so viele JSON-Dateien zu lesen? – TJain

Antwort

0

Ich würde einen Iterator auf Dateien und nur yield die beiden Spalten, die Sie wollen bauen.

Dann können Sie eine DataFrame mit diesem Iterator instanziieren.

import os 
import json 
import pandas as pd 

# Path to the dataset 
path = "../lastfm_train/" 

def data_iterator(path): 
    for root, dirs, files in os.walk(path): 
     for f in files: 
      if f.endswith('.json'): 
       fp = os.path.join(root,f) 
       with open(fp) as o: 
        data = json.load(o) 
       yield {"similars" : data["similars"], "track_id": data["track_id"]} 


df = pd.DataFrame(data_iterator(path)) 
df.set_index('track_id', inplace=True) 

diese Weise können Sie nur einmal Ihre Dateien Liste durchgehen und Sie werden die Daten vor und nach der Übergabe an DataFrame

+0

Bitte beachten Sie das Update, bereits mit Generator Verständnis. – TJain

+1

Unter Verwendung des Codes, den ich gepostet habe (mit nativem Paket 'json'), lud ich den gesamten Zugsetdatensatz in' 104 Sekunden' ein. – arthur

+0

Mein Code sowie Ihr Code laden die Untermenge (1%) in 1,04 Sekunden und daher erwartet die volle Ladung in etwas um 100s. Auf meinem Computer benötigt der Code jedoch 406s und mein Code 473s. Ich benutze eine Macbook Pro 2015 Version mit 16GB RAM. Welches Biest benutzen Sie, um perfekt auf den gesamten Datensatz zu skalieren? – TJain

2

nicht duplizieren Wenn Sie mehrere IO-Operationen auf dem Datensatz durchführen müssen, warum nicht einfach die .json Dateien in ein schnelleres IO-Format konvertieren? Wenn die Gesamtgröße Ihres Datasets 2.5G beträgt, sollte das Lesen nicht länger als eine Minute dauern, selbst auf einem Standard-Macbook, wenn es als .csv-Datei gespeichert wird.

Zum Beispiel ist neu in Pandas 0.20 das .feather Format. Eine Beschreibung des Pandas Autors finden Sie unter here. In meinen eigenen Tests auf einem Standard-Entwicklungs-Macbook habe ich 1 GB-Dateien in etwa 1 Sekunde gelesen.

Eine andere Anmerkung: Ich würde empfehlen, feather.read_data über die Top-Level-Funktion pandas.read_feather zu verwenden, da die Pandas-Version noch nicht erlaubt, eine Teilmenge von Spalten zu lesen. Sie können die Feder here herunterladen oder einfach pip install feather verwenden.

Verwandte Themen