Panda read_csv opsi low_memory dan dtype

320

Saat menelepon

df = pd.read_csv('somefile.csv')

Saya mendapat:

/Users/josh/anaconda/envs/py27/lib/python2.7/site-packages/pandas/io/parsers.py:1130: DtypeWarning: Columns (4,5,7,16) memiliki tipe campuran. Tentukan opsi dtype pada impor atau setel low_memory = Salah.

Mengapa dtypeopsi terkait low_memory, dan mengapa membuatnya Falsemembantu dengan masalah ini?

Josh
sumber
2
Saya punya pertanyaan tentang peringatan ini. Apakah indeks kolom disebutkan berbasis 0? Misalnya kolom 4 yang memiliki tipe campuran, apakah itu df [:, 4] atau df [:, 3]
maziar
@maziar saat membaca csv, secara default indeks berbasis 0 baru dibuat dan digunakan.
firelynx

Jawaban:

432

Opsi low_memory usang

The low_memoryopsi tidak benar usang, tetapi harus, karena tidak benar-benar melakukan hal berbeda [ sumber ]

Alasan Anda mendapatkan low_memoryperingatan ini adalah karena menebak dtip untuk setiap kolom sangat menuntut memori. Panda mencoba menentukan tipe apa yang akan ditetapkan dengan menganalisis data di setiap kolom.

Dtype Guessing (sangat buruk)

Panda hanya dapat menentukan tipe kolom apa yang seharusnya dimiliki setelah seluruh file dibaca. Ini berarti tidak ada yang benar-benar dapat diuraikan sebelum seluruh file dibaca kecuali Anda berisiko harus mengubah jenis kolom itu ketika Anda membaca nilai terakhir.

Perhatikan contoh satu file yang memiliki kolom bernama user_id. Ini berisi 10 juta baris di mana user_id selalu angka. Karena panda tidak dapat mengetahui bahwa itu hanya angka, panda mungkin akan menyimpannya sebagai string asli sampai ia membaca seluruh file.

Menentukan dtypes (harus selalu dilakukan)

menambahkan

dtype={'user_id': int}

dengan pd.read_csv()panggilan akan membuat panda tahu ketika mulai membaca file, bahwa ini hanya bilangan bulat.

Juga perlu dicatat adalah bahwa jika baris terakhir dalam file akan "foobar"ditulis di user_idkolom, pemuatan akan macet jika dtype di atas ditentukan.

Contoh data rusak yang pecah saat dtypes didefinisikan

import pandas as pd
try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO


csvdata = """user_id,username
1,Alice
3,Bob
foobar,Caesar"""
sio = StringIO(csvdata)
pd.read_csv(sio, dtype={"user_id": int, "username": "string"})

ValueError: invalid literal for long() with base 10: 'foobar'

dtypes biasanya hal yang numpy, baca lebih lanjut di sini: http://docs.scipy.org/doc/numpy/reference/generated/numpy.dtype.html

Dtypes apa yang ada?

Kami memiliki akses ke tipe numpy: float, int, bool, timedelta64 [ns] dan datetime64 [ns]. Perhatikan bahwa dtypes tanggal / waktu numpy tidak mengetahui zona waktu.

Panda memperluas rangkaian tipe ini dengan miliknya sendiri:

'datetime64 [ns,]' Yang merupakan cap waktu sadar zona waktu.

'kategori' yang pada dasarnya adalah enum (string diwakili oleh kunci integer untuk disimpan

'periode []' Tidak perlu bingung dengan timedelta, objek ini sebenarnya berlabuh ke periode waktu tertentu

'Jarang', 'Jarang [int]', 'Jarang [float]' adalah untuk data jarang atau 'Data yang memiliki banyak lubang di dalamnya' Alih-alih menyimpan NaN atau Tidak Ada dalam kerangka data yang menghilangkan objek, menghemat ruang .

'Interval' adalah topiknya sendiri tetapi penggunaan utamanya adalah untuk pengindeksan. Lihat lebih lanjut di sini

'Int8', 'Int16', 'Int32', 'Int64', 'UInt8', 'UInt16', 'UInt32', 'UInt64' adalah semua bilangan bulat spesifik panda yang dapat dibatalkan, tidak seperti varian numpy.

'string' adalah tipe khusus untuk bekerja dengan data string dan memberikan akses ke .stratribut pada seri.

'boolean' seperti 'bool' yang numpy tetapi juga mendukung data yang hilang.

Baca referensi selengkapnya di sini:

Referensi dtype panda

Gotchas, peringatan, catatan

Pengaturan dtype=objectakan membungkam peringatan di atas, tetapi tidak akan membuatnya lebih hemat memori, hanya proses yang efisien jika ada.

Pengaturan dtype=unicodetidak akan melakukan apa pun, karena untuk numpy, a unicodedirepresentasikan sebagai object.

Penggunaan konverter

@sparrow dengan benar menunjukkan penggunaan konverter untuk menghindari panda yang meledak saat bertemu 'foobar'di kolom yang ditentukan int. Saya ingin menambahkan bahwa konverter sangat berat dan tidak efisien untuk digunakan dalam panda dan harus digunakan sebagai upaya terakhir. Ini karena proses read_csv adalah proses tunggal.

File CSV dapat diproses baris demi baris dan karenanya dapat diproses oleh banyak konverter secara paralel dengan lebih efisien hanya dengan memotong file menjadi segmen dan menjalankan banyak proses, sesuatu yang tidak didukung panda. Tapi ini cerita yang berbeda.

firelynx
sumber
6
Jadi, mengingat bahwa pengaturan a dtype=objecttidak lebih hemat memori, apakah ada alasan untuk mengacaukannya selain menyingkirkan kesalahan?
zthomas.nc
6
@ zthomas.nc ya, Pandas tidak perlu repot-repot menguji apa yang ada di kolom. Secara teoritis menghemat beberapa memori saat memuat (tetapi tidak ada setelah memuat selesai) dan secara teoritis menyimpan beberapa siklus CPU (yang Anda tidak akan melihat karena disk I / O akan menjadi hambatan.
firelynx
5
"Juga patut dicatat adalah bahwa jika baris terakhir dalam file akan memiliki" foobar "ditulis di kolom user_id, pemuatan akan macet jika dtype di atas ditentukan." apakah ada opsi "memaksa" yang dapat digunakan untuk membuang baris ini alih-alih menabrak?
sparrow
5
@ Sparrow mungkin ada, tapi terakhir kali saya menggunakannya ada bug. Mungkin diperbaiki di versi panda terbaru. error_bad_lines=False, warn_bad_lines=Trueharus melakukan trik. Dokumentasi mengatakan itu hanya valid dengan parser C. Ia juga mengatakan parser default adalah Tidak ada yang membuatnya sulit untuk mengetahui mana yang merupakan default.
firelynx
5
@nealmcb Anda dapat membaca kerangka data dengan nrows=100sebagai argumen dan kemudian lakukan df.dtypesuntuk melihat dtypes yang Anda dapatkan. Namun, ketika membaca seluruh kerangka data dengan dtypes ini, pastikan untuk melakukan try/exceptsehingga Anda menangkap dugaan dtype yang salah. Data kotor lho.
firelynx
50

Mencoba:

dashboard_df = pd.read_csv(p_file, sep=',', error_bad_lines=False, index_col=False, dtype='unicode')

Menurut dokumentasi panda:

dtype: Ketik nama atau diktik kolom -> jenis

Sedangkan untuk low_memory, itu Benar secara default dan belum didokumentasikan. Saya pikir itu tidak relevan. Pesan galatnya generik, jadi Anda tidak perlu repot dengan low_memory. Semoga ini bisa membantu dan beri tahu saya jika Anda memiliki masalah lebih lanjut

hd1
sumber
1
Menambahkan dtype=unicodedihasilkan: NameError: name 'unicode' is not defined. Tetapi memasukkan unicodetanda kutip (seperti dalam 'unicode') tampaknya berhasil!
sedeh
5
@sedeh Anda dapat menentukan dtypes sebagai tipe python atau sebagai numpy.dtype('unicode'). Ketika Anda memberikan opsi dtype string, itu akan mencoba untuk melemparkannya melalui numpy.dtype()pabrik secara default. Menentukan 'unicode'sebenarnya tidak akan melakukan apa-apa, hanya unicodes upcasted objects. Anda akan mendapatkandtype='object'
firelynx
43
df = pd.read_csv('somefile.csv', low_memory=False)

Ini harus menyelesaikan masalah. Saya mendapatkan kesalahan yang persis sama, ketika membaca 1,8M baris dari CSV.

Neal
sumber
51
Ini membungkam kesalahan, tetapi sebenarnya tidak mengubah apa pun.
firelynx
2
Saya memiliki masalah yang sama saat menjalankan datafile 1.5gb
Sitz Blogz
18

Seperti yang disebutkan sebelumnya oleh firelynx jika dtype ditentukan secara eksplisit dan ada data campuran yang tidak kompatibel dengan dtype itu maka memuat akan macet. Saya menggunakan konverter seperti ini sebagai solusi untuk mengubah nilai dengan tipe data yang tidak kompatibel sehingga data masih bisa dimuat.

def conv(val):
    if not val:
        return 0    
    try:
        return np.float64(val)
    except:        
        return np.float64(0)

df = pd.read_csv(csv_file,converters={'COL_A':conv,'COL_B':conv})
burung gereja
sumber
2

Saya memiliki masalah serupa dengan file ~ 400MB. Pengaturan low_memory=Falsemelakukan trik untuk saya. Lakukan hal-hal sederhana terlebih dahulu, saya akan memeriksa bahwa frame data Anda tidak lebih besar dari memori sistem Anda, reboot, hapus RAM sebelum melanjutkan. Jika Anda masih mengalami kesalahan, pastikan .csvfile Anda baik-baik saja, lihat cepat di Excel dan pastikan tidak ada kerusakan yang jelas. Data asli yang rusak dapat menyebabkan ...

Dr Nigel
sumber
1

Saya menghadapi masalah serupa ketika memproses file csv besar (6 juta baris). Saya memiliki tiga masalah: 1. file berisi karakter aneh (tetap menggunakan pengkodean) 2. datatype tidak ditentukan (tetap menggunakan properti dtype) 3. Menggunakan di atas saya masih menghadapi masalah yang berkaitan dengan file_format yang tidak bisa didefinisikan berdasarkan nama file (tetap menggunakan coba .. kecuali ..)

df = pd.read_csv(csv_file,sep=';', encoding = 'ISO-8859-1',
                 names=['permission','owner_name','group_name','size','ctime','mtime','atime','filename','full_filename'],
                 dtype={'permission':str,'owner_name':str,'group_name':str,'size':str,'ctime':object,'mtime':object,'atime':object,'filename':str,'full_filename':str,'first_date':object,'last_date':object})

try:
    df['file_format'] = [Path(f).suffix[1:] for f in df.filename.tolist()]
except:
    df['file_format'] = ''
Wim Folkerts
sumber
-1

Ini bekerja untuk saya low_memory = Falsesaat mengimpor DataFrame. Itulah semua perubahan yang berhasil bagi saya:

df = pd.read_csv('export4_16.csv',low_memory=False)
Rajat Saxena
sumber