Inconsistente pandas read_csv dtype inference en la mayoría de la columna de cadena entera en un enorme archivo TSV

Tengo un archivo separado por tabulaciones con una columna que debe interpretarse como una cadena, pero muchas de las entradas son enteros. Con archivos pequeños, read_csv interpreta correctamente la columna como una cadena después de ver algunos valores no enteros, pero con archivos más grandes, esto no funciona:

import pandas as pd df = pd.DataFrame({'a':['1']*100000 + ['X']*100000 + ['1']*100000, 'b':['b']*300000}) df.to_csv('test', sep='\t', index=False, na_rep='NA') df2 = pd.read_csv('test', sep='\t') print df2['a'].unique() for a in df2['a'][262140:262150]: print repr(a) 

salida:

 ['1' 'X' 1] '1' '1' '1' '1' 1 1 1 1 1 1 

Es interesante que 262144 es una potencia de 2, por lo que creo que la inferencia y la conversión se están produciendo en partes, pero se está saltando algunas partes.

Estoy bastante seguro de que esto es un error, pero me gustaría una solución alternativa que quizás use comillas, aunque agregar quoting = csv.QUOTE_NONNUMERIC para leer y escribir no soluciona el problema. Idealmente, podría solucionar este problema citando mis datos de cadena y de alguna manera forzar a los pandas a no hacer ninguna inferencia sobre los datos citados.

Utilizando pandas 0.12.0

Has engañado al analizador read_csv aquí (y para ser justos, no creo que siempre se pueda esperar que salga correctamente sin importar lo que le eches) … ¡pero sí, podría ser un error !

Como @Steven señala, puedes usar el argumento de los convertidores de read_csv :

 df2 = pd.read_csv('test', sep='\t', converters={'a': str}) 

Una solución perezosa es solo parchear esto después de haber leído el archivo:

 In [11]: df2['a'] = df2['a'].astype('str') # now they are equal In [12]: pd.util.testing.assert_frame_equal(df, df2) 

Nota: Si está buscando una solución para almacenar DataFrames , por ejemplo, entre sesiones, tanto Pickle como HDF5Store son soluciones excelentes que no se verán afectadas por este tipo de errores de análisis (y serán considerablemente más rápidos). Ver: Cómo almacenar el dataframe usando PANDAS, Python

Para evitar que Pandas deduzca su tipo de datos, proporcione un argumento de converters a read_csv :

converters : dict. Opcional

Dictado de funciones para la conversión de valores en determinadas columnas. Las claves pueden ser enteros o tags de columna

Para tu archivo esto se vería como:

 df2 = pd.read_csv('test', sep='\t', converters={'a':str}) 

Mi lectura de los documentos es que no es necesario especificar convertidores para cada columna. Las pandas deben continuar inferiendo el tipo de datos de las columnas no especificadas.