2013-04-09 9 views
6

Ich versuche, zufällige Zeilen aus einer HDFStore-Tabelle von etwa 1 GB auszuwählen. Die RAM-Nutzung explodiert, wenn ich nach etwa 50 zufälligen Zeilen frage.HDFStore: table.select und RAM-Auslastung

Ich benutze Pandas 0-11-dev, python 2.7, linux64.

In diesem ersten Fall die RAM-Auslastung, die Größe von chunk

with pd.get_store("train.h5",'r') as train: 
for chunk in train.select('train',chunksize=50): 
    pass 

In diesem zweiten Fall paßt, wie es scheint, die ganze Tabelle in RAM

r=random.choice(400000,size=40,replace=False) 
train.select('train',pd.Term("index",r)) 

In diesem letzten Fall geladen wird, Die RAM-Nutzung entspricht dem Äquivalent chunk Größe

r=random.choice(400000,size=30,replace=False)  
train.select('train',pd.Term("index",r)) 

Ich bin verwundert, warum der Wechsel von 30 auf 40 zufällige Reihen einen so dramatischen Anstieg der RAM-Nutzung bewirkt.

Notiz wird die Tabelle indiziert, wenn eine solche erstellt, dass index = Bereich (nrows (Tabelle)) mit dem folgenden Code:

def txtfile2hdfstore(infile, storefile, table_name, sep="\t", header=0, chunksize=50000): 
    max_len, dtypes0 = txtfile2dtypes(infile, sep, header, chunksize) 

    with pd.get_store(storefile,'w') as store: 
     for i, chunk in enumerate(pd.read_table(infile,header=header,sep=sep,chunksize=chunksize, dtype=dict(dtypes0))): 
      chunk.index= range(chunksize*(i), chunksize*(i+1))[:chunk.shape[0]] 
      store.append(table_name,chunk, min_itemsize={'values':max_len}) 

Dank für Einsicht

EDIT Zelazny7

ANTWORTEN

Hier ist die Datei, die ich verwendet habe, um Train.csv in train.h5 zu schreiben. Ich schrieb dies mit Elementen der Zelazny7 Code von How to trouble-shoot HDFStore Exception: cannot find the correct atom type

import pandas as pd 
import numpy as np 
from sklearn.feature_extraction import DictVectorizer 


def object_max_len(x): 
    if x.dtype != 'object': 
     return 
    else: 
     return len(max(x.fillna(''), key=lambda x: len(str(x)))) 

def txtfile2dtypes(infile, sep="\t", header=0, chunksize=50000): 
    max_len = pd.read_table(infile,header=header, sep=sep,nrows=5).apply(object_max_len).max() 
    dtypes0 = pd.read_table(infile,header=header, sep=sep,nrows=5).dtypes 

    for chunk in pd.read_table(infile,header=header, sep=sep, chunksize=chunksize): 
     max_len = max((pd.DataFrame(chunk.apply(object_max_len)).max(),max_len)) 
     for i,k in enumerate(zip(dtypes0[:], chunk.dtypes)): 
      if (k[0] != k[1]) and (k[1] == 'object'): 
       dtypes0[i] = k[1] 
    #as of pandas-0.11 nan requires a float64 dtype 
    dtypes0.values[dtypes0 == np.int64] = np.dtype('float64') 
    return max_len, dtypes0 


def txtfile2hdfstore(infile, storefile, table_name, sep="\t", header=0, chunksize=50000): 
    max_len, dtypes0 = txtfile2dtypes(infile, sep, header, chunksize) 

    with pd.get_store(storefile,'w') as store: 
     for i, chunk in enumerate(pd.read_table(infile,header=header,sep=sep,chunksize=chunksize, dtype=dict(dtypes0))): 
      chunk.index= range(chunksize*(i), chunksize*(i+1))[:chunk.shape[0]] 
      store.append(table_name,chunk, min_itemsize={'values':max_len}) 

Applied als

txtfile2hdfstore('Train.csv','train.h5','train',sep=',') 
+0

Sie scheinen HDFStore in ähnlicher Weise zu verwenden, wie ich es verwenden möchte. Ich hatte nicht die Zeit, um den Wrapper-Code zu erstellen, der viel von dem Speichern und Abrufen behandelt. Würde es Ihnen etwas ausmachen, Ihren 'txtfile2dtypes' Code zu teilen? Haben Ihre Daten auch viele Charakterdaten? Ich habe Probleme beim Speichern einer CSV-Datei in einem HDFStore mit variablen Zeichendaten. Die Dateigröße explodiert, weil ich 'min_itemsize' auf einen so großen Wert setzen muss. Ich warte gespannt auf die Hinzufügung einer 'truncate'-Option. – Zelazny7

+1

@ Zelazny7 Ich habe den Thread mit dem Code aktualisiert. Tatsächlich benutze ich es auf den gleichen Daten wie Ihre, die Kaggle-Bulldozer-Sache.Ich habe die kategorischen Variablen noch nicht erfunden, um 'sklearn' zu verwenden. – user17375

+1

Vielen Dank! Es sieht so aus, als ob Ihre Dateigröße auf die gleiche Weise wie bei mir aufgeht. Die ~ 120 MB-Datei endet über 1 GB. Ich frage mich, ob Sie oder Jeff wissen würden, ob es besser ist, 'Objekt'-Spalten variabler Länge (wirklich nur Zeichenfolgen) zu speichern, indem Sie 'put' verwenden und jede Textspalte als ihr eigenes HDFStore-Objekt behalten. – Zelazny7

Antwort

6

Dies ist ein bekanntes Problem, finden Sie in der Referenz hier: https://github.com/pydata/pandas/pull/2755

Wesentlichen die Abfrage in eine numexpr gedreht wird Ausdruck für die Bewertung. Es gibt ein Problem , wo ich nicht viele or Bedingungen zu numexpr übergeben kann (es hängt von der Gesamtlänge des generierten Ausdrucks ab).

Also beschränke ich den Ausdruck, den wir an numexpr übergeben. Wenn sie eine bestimmte Anzahl von or Bedingungen überschreitet, erfolgt die Abfrage als Filter und nicht als Auswahl im Kernel. Grundsätzlich bedeutet dies, dass die Tabelle gelesen und dann neu indiziert wird.

Dies ist auf meiner Erweiterungsliste: https://github.com/pydata/pandas/issues/2391 (17).

Um dieses Problem zu umgehen, teilen Sie Ihre Abfragen einfach in mehrere auf und fassen Sie die Ergebnisse zusammen. Sollte viel schneller sein und eine konstante Menge an Speicher verwenden

+1

Ok Danke. Ich habe den Thema-Thread verpasst, ich hätte zuerst die GitHub-Foren durchsuchen sollen. Übrigens, ich merke nur, dass Sie der Entwickler von hdfstore sind, also vielen Dank für die tolle Arbeit! – user17375

+0

Das ist ziemlich obskur und unglücklich leicht zu verpassen :) – Jeff

Verwandte Themen