2016-09-27 4 views
8

Ich habe eine große Datei (2 GB) von kategorischen Daten (meist "Nan" - aber hier und da mit tatsächlichen Werten gefüllt), die zu groß ist, in einen einzelnen Datenrahmen zu lesen . Ich hatte eine ziemlich schwierige Zeit mit einem Objekt zu kommen, um alle einzigartigen Werte für jede Spalte zu speichern (Welches ist mein Ziel - schließlich muss ich dies für die Modellierung zu faktorisieren)Der Pythonic Weg, um eine Liste von Listen zu wachsen

Was ich damit endete tun, war das Lesen der Datei in Chunks in einen Datenrahmen und dann die eindeutigen Werte jeder Spalte und speichern sie in einer Liste von Listen. Meine Lösung funktioniert, schien aber am unpythonischsten - gibt es einen saubereren Weg, dies in Python (Version 3.5) zu erreichen. Ich kenne die Anzahl der Spalten (~ 2100).

import pandas as pd 
#large file of csv separated text data 
data=pd.read_csv("./myratherlargefile.csv",chunksize=100000, dtype=str) 

collist=[] 
master=[] 
i=0 
initialize=0 
for chunk in data: 
    #so the first time through I have to make the "master" list 
    if initialize==0: 
     for col in chunk: 
      #thinking about this, i should have just dropped this col 
      if col=='Id': 
       continue 
      else: 
       #use pd.unique as a build in solution to get unique values 
       collist=chunk[col][chunk[col].notnull()].unique().tolist() 
       master.append(collist) 
       i=i+1 
    #but after first loop just append to the master-list at 
    #each master-list element 
    if initialize==1: 
     for col in chunk: 
      if col=='Id': 
       continue 
      else: 
       collist=chunk[col][chunk[col].notnull()].unique().tolist() 
       for item in collist: 
        master[i]=master[i]+collist 
       i=i+1 
    initialize=1 
    i=0 

danach, meine letzte Aufgabe für alle eindeutigen Werte ist wie folgt:

i=0 
names=chunk.columns.tolist() 
for item in master: 
    master[i]=list(set(item)) 
    master[i]=master[i].append(names[i+1]) 
    i=i+1 

so beherrschen [i] gibt mir die Spaltennamen und dann eine Liste von eindeutigen Werten - grobe, aber es funktioniert - mein Hauptanliegen ist es, die Liste nach Möglichkeit "besser" zu erstellen.

+0

zu verwenden, haben Sie einen Generator lazily betrachtet mit, um die Datei zu lesen? (Suche das Yield-Schlüsselwort) – salparadise

+0

Das könnte den Trick machen. Ich bin noch nicht gut mit Iteratoren und Generatoren - aber ein flüchtiger Blick auf das Yield-Schlüsselwort, wie vorgeschlagen, scheint in die richtige Richtung zu gehen. – RDS

+0

Dies ist tatsächlich mit einem Generator unter der Haube. Die Chunksize macht genau das. Aus Neugier bist du auf einem 32 oder 64 Bit-Rechner/Python? 'importieren sys; print (sys.maxsize) 'sollte so lange arbeiten, wie Sie Python ausführen 2.6 –

Antwort

8

Ich würde anstelle einer list von list s vorschlagen, mit einer collections.defaultdict(set).

Sagen Sie bitte mit

uniques = collections.defaultdict(set) 

Nun ist die Schleife so etwas wie dieses werden beginnen:

for chunk in data: 
    for col in chunk: 
     uniques[col] = uniques[col].union(chunk[col].unique()) 

Beachten Sie, dass:

  1. defaultdict hat immer ein set für uniques[col] (das ist wofür es da ist, also kannst duüberspringenund so.

  2. Für eine gegebenes col Sie einfach mit der Vereinigung des aktuellen Satzes den Eintrag aktualisieren (die zunächst leer ist, aber es spielt keine Rolle) und die neuen, einzigartigen Elemente.

bearbeiten

Wie Raymond Hettinger stellt fest (Danke!), Ist es besser

 uniques[col].update(chunk[col].unique()) 
+0

Wow - das macht den Trick in 1/3 der Code. Ich muss auch an Diktaten arbeiten. Gut gemacht. – RDS

+0

@ RDS Danke. Ich mochte deine Frage. Alles Gute. –

+0

Dies würde mit '' set.update'' besser aussehen als mit '' set.union''. –

Verwandte Themen