Pandas read_csv low_memory y dtype opciones

Al llamar

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

Yo obtengo:

/Users/josh/anaconda/envs/py27/lib/python2.7/site-packages/pandas/io/parsers.py:1130: DtypeWarning: las columnas (4,5,7,16) tienen tipos mixtos. Especifique la opción dtype en la importación o establezca low_memory = False.

¿Por qué la opción dtype relacionada con low_memory y por qué sería False ayudar con este problema?

La opción low_memory en desuso

La opción low_memory no está en desuso adecuadamente, pero debería estarlo, ya que en realidad no hace nada diferente [ fuente ]

La razón por la que recibe esta advertencia de low_memory es porque los tipos de adivinación para cada columna requieren mucha memoria. Pandas intenta determinar qué tipo de dato establecer mediante el análisis de los datos en cada columna.

Dtype Guessing (muy mal)

Las pandas solo pueden determinar qué tipo de columna debe tener una vez que se lee el archivo completo. Esto significa que realmente no se puede analizar nada antes de leer todo el archivo a menos que se arriesgue a tener que cambiar el tipo de columna cuando lea el último valor.

Considere el ejemplo de un archivo que tiene una columna llamada user_id. Contiene 10 millones de filas donde el user_id es siempre números. Como los pandas no pueden saber que son solo números, probablemente lo mantendrá como las cadenas originales hasta que haya leído el archivo completo.

Especificación de tipos (siempre debe hacerse)

añadiendo

 dtype={'user_id': int} 

a la llamada pd.read_csv() hará que los pandas sepan cuándo empieza a leer el archivo, que esto es solo enteros.

También vale la pena señalar que si la última línea del archivo tuviera "foobar" escrito en la columna user_id , la carga se bloquearía si se especificara el tipo de texto anterior.

Ejemplo de datos rotos que se rompen cuando se definen dtypes

 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": object}) ValueError: invalid literal for long() with base 10: 'foobar' 

Los tipos de datos suelen ser una cuestión de números, lea más sobre ellos aquí: http://docs.scipy.org/doc/numpy/reference/generated/numpy.dtype.html

¿Qué dtypes existen?

Estos son los tipos de datos que también se aceptan en pandas.

 [numpy.generic, [[numpy.number, [[numpy.integer, [[numpy.signedinteger, [numpy.int8, numpy.int16, numpy.int32, numpy.int64, numpy.int64, numpy.timedelta64]], [numpy.unsignedinteger, [numpy.uint8, numpy.uint16, numpy.uint32, numpy.uint64, numpy.uint64]]]], [numpy.inexact, [[numpy.floating, [numpy.float16, numpy.float32, numpy.float64, numpy.float128]], [numpy.complexfloating, [numpy.complex64, numpy.complex128, numpy.complex256]]]]]], [numpy.flexible, [[numpy.character, [numpy.bytes_, numpy.str_]], [numpy.void, [numpy.record]]]], numpy.bool_, numpy.datetime64, numpy.object_]] 

Pandas también agrega dos dtypes: categorical y datetime64[ns, tz] que no están disponibles en números

Pandas dtype referencia

Gotchas, advertencias, notas

La configuración de dtype=object silenciará la advertencia anterior, pero no la hará más eficiente en memoria, solo procesará la eficiencia en todo caso.

Configurar dtype=unicode no hará nada, ya que para numpy, un unicode se representa como un object .

Uso de convertidores

@sparrow señala correctamente el uso de convertidores para evitar que los pandas exploten al encontrar 'foobar' en una columna especificada como int . Me gustaría agregar que los convertidores son muy pesados ​​e ineficientes de usar en pandas y deberían usarse como último recurso. Esto se debe a que el proceso read_csv es un proceso único.

Los archivos CSV pueden procesarse línea por línea y, por lo tanto, pueden ser procesados ​​por varios convertidores en paralelo de manera más eficiente simplemente cortando el archivo en segmentos y ejecutando múltiples procesos, algo que pandas no admite. Pero esta es una historia diferente.

Tratar:

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

Según la documentación de los pandas:

dtype: escriba nombre o dict de columna -> escriba

En cuanto a low_memory, es True por defecto y aún no está documentado. Aunque no creo que sea relevante. El mensaje de error es genérico, por lo que no debería tener que meterse con low_memory de todos modos. Espero que esto ayude y hágame saber si tiene más problemas.

 df = pd.read_csv('somefile.csv', low_memory=False) 

Esto debería resolver el problema. Obtuve exactamente el mismo error, al leer 1.8M filas de un CSV.

Como mencionó anteriormente firelynx si dtype se especifica explícitamente y hay datos mixtos que no son compatibles con ese dtype, la carga se bloqueará. Utilicé un convertidor como este como una solución para cambiar los valores con un tipo de datos incompatible para que los datos aún puedan cargarse.

 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}) 

Tuve un problema similar con un archivo de ~ 400MB. Establecer low_memory=False hizo el truco para mí. Haga las cosas simples primero, verificaría que su dataframe no sea más grande que la memoria del sistema, reinicie, borre la memoria RAM antes de continuar. Si aún tiene errores, vale la pena asegurarse de que su archivo .csv esté bien, eche un vistazo rápido en Excel y asegúrese de que no haya daños evidentes. Los datos originales rotos pueden causar esgulps …

Me funcionó con low_memory = False al importar un DataFrame. Ese es todo el cambio que funcionó para mí:

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