Saya menjelajahi peralihan ke python dan panda sebagai pengguna SAS lama.
Namun, ketika menjalankan beberapa tes hari ini, saya terkejut bahwa python kehabisan memori ketika mencoba pandas.read_csv()
file csv 128mb. Itu memiliki sekitar 200.000 baris dan 200 kolom yang sebagian besar data numerik.
Dengan SAS, saya dapat mengimpor file csv ke dalam dataset SAS dan ukurannya bisa sebesar hard drive saya.
Apakah ada analogi pandas
?
Saya secara teratur bekerja dengan file besar dan tidak memiliki akses ke jaringan komputasi terdistribusi.
Jawaban:
Pada prinsipnya itu tidak boleh kehabisan memori, tetapi saat ini ada masalah memori dengan
read_csv
pada file besar yang disebabkan oleh beberapa masalah internal Python yang kompleks (ini tidak jelas tetapi sudah diketahui sejak lama: http://github.com/pydata / pandas / issues / 407 ).Saat ini tidak ada solusi yang tepat (ini yang membosankan: Anda dapat mentranskripsikan file baris demi baris menjadi array NumPy yang telah dialokasikan sebelumnya atau file yang dipetakan memori--
np.mmap
), tetapi ini adalah solusi yang akan saya kerjakan dalam waktu dekat. Solusi lain adalah membaca file dalam potongan-potongan kecil (gunakaniterator=True, chunksize=1000
) lalu gabungkan lalu denganpd.concat
. Masalahnya muncul saat Anda menarik seluruh file teks ke dalam memori dalam satu slurp besar.sumber
Kami tentu saja benar! Saya hanya akan memberikan sedikit contoh kode yang lebih lengkap. Saya memiliki masalah yang sama dengan file 129 Mb, yang diselesaikan dengan:
import pandas as pd tp = pd.read_csv('large_dataset.csv', iterator=True, chunksize=1000) # gives TextFileReader, which is iterable with chunks of 1000 rows. df = pd.concat(tp, ignore_index=True) # df is DataFrame. If errors, do `list(tp)` instead of `tp`
sumber
df = concate(tp, ignore_index=True)
?AssertionError: first argument must be a list-like of pandas objects, you passed an object of type "TextFileReader"
. Tahu apa yang terjadi di sini?pd.concat(list(tp), ignore_index=True)
Ini adalah utas yang lebih lama, tetapi saya hanya ingin membuang solusi solusi saya di sini. Saya awalnya mencoba
chunksize
parameter (bahkan dengan nilai yang cukup kecil seperti 10000), tetapi tidak banyak membantu; masih memiliki masalah teknis dengan ukuran memori (CSV saya ~ 7,5 Gb).Saat ini, saya baru saja membaca potongan file CSV dalam pendekatan for-loop dan menambahkannya misalnya, ke database SQLite langkah demi langkah:
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()
sumber
pandas.read_csv
langsung mengembalikan (setidaknya pada versi yang saya gunakan saat ini) sebuah iterator jika Anda hanya menyediakaniterator=True
danchunksize=chunksize
. Oleh karena itu, Anda hanya perlu melakukanfor
loop padapd.read_csv
panggilan, alih-alih membuat instance ulang setiap saat. Namun, ini hanya biaya overhead panggilan, mungkin tidak ada dampak yang signifikan.iterator=True
danchunksize
parameter yang sudah ada saat itu jika saya ingat benar. Mungkin ada bug di versi lama yang menyebabkan memori meledak - Saya akan mencobanya lagi lain kali saat saya membaca DataFrame besar di Pandas (Saya kebanyakan menggunakan Blaze sekarang untuk tugas-tugas seperti itu)Di bawah ini adalah alur kerja saya.
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')
Berdasarkan ukuran file Anda, Anda sebaiknya mengoptimalkan ukuran chunksize.
for chunk in chunks: chunk.to_sql(name='Table', if_exists='append', con=con) count += 1 print(count)
Setelah memiliki semua data dalam database, Anda bisa membuat kueri yang Anda butuhkan dari database.
sumber
Jika Anda ingin memuat file csv yang besar, dask mungkin merupakan pilihan yang baik. Ini meniru api panda, jadi rasanya sangat mirip dengan panda
tautan untuk berjemur di github
sumber
Anda dapat menggunakan Pytable daripada pandas df. Ini dirancang untuk kumpulan data besar dan format file dalam hdf5. Sehingga waktu pengerjaannya relatif cepat.
sumber