Duża, trwała ramka danych w pandach

[2]}badam przejście na python i pandas jako wieloletni użytkownik SAS.

Jednak podczas testów dziwiłem się, że pythonowi zabrakło pamięci podczas próby pandas.read_csv() pliku csv 128MB. Miał około 200 000 wierszy i 200 kolumn w większości danych liczbowych.

Z SAS, mogę zaimportować plik csv do zestawu danych SAS i może być tak duży, jak mój dysk twardy.

Czy jest coś analogicznego w pandas?

Regularnie pracuję z dużymi plikami i nie mieć dostęp do rozproszonej sieci obliczeniowej.

Author: piRSquared, 2012-07-24

6 answers

W zasadzie nie powinno zabraknąć pamięci, ale obecnie występują problemy z pamięcią read_csv Na dużych plikach spowodowane przez niektóre złożone problemy wewnętrzne Pythona (jest to niejasne, ale jest znane od dawna: http://github.com/pydata/pandas/issues/407).

W tej chwili nie ma idealnego rozwiązania( tutaj jest żmudne: możesz transkrybować plik wiersz po wierszu do wstępnie przydzielonej tablicy NumPy lub pliku mapowanego pamięcią--np.mmap), ale nad nim będę pracował w w niedalekiej przyszłości. Innym rozwiązaniem jest odczytanie pliku w mniejszych kawałkach (użyj iterator=True, chunksize=1000), a następnie połączenie z pd.concat. Problem pojawia się, gdy ciągniesz cały plik tekstowy do pamięci w jednym wielkim slurp.

 73
Author: Wes McKinney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-09 02:46:50

Wes ma oczywiście rację! Po prostu dzwonię, aby podać trochę bardziej kompletny przykładowy kod. Miałem ten sam problem z plikiem 129 Mb, który został rozwiązany przez:

from pandas import *

tp = read_csv('large_dataset.csv', iterator=True, chunksize=1000)  # gives TextFileReader, which is iterable with chunks of 1000 rows.
df = concat(tp, ignore_index=True)  # df is DataFrame. If errors, do `list(tp)` instead of `tp`
 73
Author: fickludd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-02 17:25:58

To jest starszy wątek, ale chciałem rzucić moje rozwiązanie obejścia tutaj. Początkowo próbowałem parametru chunksize (nawet przy dość małych wartościach, takich jak 10000), ale to niewiele pomogło; nadal miałem problemy techniczne z rozmiarem pamięci (mój CSV wynosił ~ 7.5 Gb).

W tej chwili po prostu czytam fragmenty plików CSV w podejściu for-loop i dodaję je np. do bazy danych SQLite krok po kroku:

import pandas as pd
import sqlite3
from pandas.io import sql
import subprocess

# In and output file paths
in_csv = '../data/my_large.csv'
out_sqlite = '../data/my.sqlite'

table_name = 'my_table' # name for the SQLite database table
chunksize = 100000 # number of lines to process at each iteration

# columns that should be read from the CSV file
columns = ['molecule_id','charge','db','drugsnow','hba','hbd','loc','nrb','smiles']

# Get number of lines in the CSV file
nlines = subprocess.check_output('wc -l %s' % in_csv, shell=True)
nlines = int(nlines.split()[0]) 

# connect to database
cnx = sqlite3.connect(out_sqlite)

# Iteratively read CSV and dump lines into the SQLite table
for i in range(0, nlines, chunksize):

    df = pd.read_csv(in_csv,  
            header=None,  # no header, define column header manually later
            nrows=chunksize, # number of rows to read at each iteration
            skiprows=i)   # skip rows that were already read

    # columns to read        
    df.columns = columns

    sql.to_sql(df, 
                name=table_name, 
                con=cnx, 
                index=False, # don't use CSV file index
                index_label='molecule_id', # use a unique column from DataFrame as index
                if_exists='append') 
cnx.close()    
 36
Author: Sebastian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-06 20:46:56

Jeśli chcesz załadować ogromne pliki csv, dask może być dobrą opcją. Imituje API pand, więc wydaje się dość podobny do pand

Link do dask na github

 3
Author: user8108173,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-08 21:54:47

Poniżej jest mój przepływ pracy.

import sqlalchemy as sa
import pandas as pd
import psycopg2

count = 0
con = sa.create_engine('postgresql://postgres:pwd@localhost:00001/r')
#con = sa.create_engine('sqlite:///XXXXX.db') SQLite
chunks = pd.read_csv('..file', chunksize=10000, encoding="ISO-8859-1",
                     sep=',', error_bad_lines=False, index_col=False, dtype='unicode')

Bazuj na rozmiarze pliku, lepiej zoptymalizuj rozmiar chunksize.

 for chunk in chunks:
        chunk.to_sql(name='Table', if_exists='append', con=con)
        count += 1
        print(count)

Po umieszczeniu wszystkich danych w bazie danych, możesz odpytywać te, których potrzebujesz z bazy danych.

 2
Author: Wen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-19 21:45:28

Możesz użyć Pytable zamiast pandy df. Jest przeznaczony dla dużych zbiorów danych, a format pliku jest w hdf5. Tak więc czas przetwarzania jest stosunkowo szybki.

 1
Author: Elm662,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-10 17:38:48