pandas incapaces de leer desde un gran objeto StringIO

Estoy usando pandas para administrar una gran variedad de enteros de 8 bytes. Estos enteros se incluyen como elementos delimitados por espacios de una columna en un archivo CSV delimitado por comas, y el tamaño de la matriz es de aproximadamente 10000×10000.

Pandas es capaz de leer rápidamente los datos delimitados por comas de las primeras columnas como un Marco de datos, y también almacenar rápidamente las cadenas delimitadas por espacios en otro Marco de datos con una molestia mínima. El problema viene cuando trato de convertir la tabla de una sola columna de cadenas delimitadas por espacios a un DataFrame de enteros de 8 bits.

He probado lo siguiente:

intdata = pd.DataFrame(strdata.columnname.str.split().tolist(), dtype='uint8') 

Pero el uso de la memoria es insoportable: el valor de 10 MB de enteros consume 2 GB de memoria. Me dicen que es una limitación del idioma y no hay nada que pueda hacer al respecto en este caso.

Como una posible solución, se me recomendó guardar los datos de la cadena en un archivo CSV y luego volver a cargar el archivo CSV como un dataframe de enteros delimitados por espacios. Esto funciona bien, pero para evitar la desaceleración que se produce al escribir en el disco, intenté escribir en un objeto StringIO.

Aquí hay un ejemplo mínimo que no funciona:

 import numpy as np import pandas as pd from cStringIO import StringIO a = np.random.randint(0,256,(10000,10000)).astype('uint8') b = pd.DataFrame(a) c = StringIO() b.to_csv(c, delimiter=' ', header=False, index=False) d = pd.io.parsers.read_csv(c, delimiter=' ', header=None, dtype='uint8') 

Que produce el siguiente mensaje de error:

 Traceback (most recent call last): File "", line 1, in  File "/usr/lib64/python2.7/site-packages/pandas/io/parsers.py", line 443, in parser_f return _read(filepath_or_buffer, kwds) File "/usr/lib64/python2.7/site-packages/pandas/io/parsers.py", line 228, in _read parser = TextFileReader(filepath_or_buffer, **kwds) File "/usr/lib64/python2.7/site-packages/pandas/io/parsers.py", line 533, in __init__ self._make_engine(self.engine) File "/usr/lib64/python2.7/site-packages/pandas/io/parsers.py", line 670, in _make_engine self._engine = CParserWrapper(self.f, **self.options) File "/usr/lib64/python2.7/site-packages/pandas/io/parsers.py", line 1032, in __init__ self._reader = _parser.TextReader(src, **kwds) File "parser.pyx", line 486, in pandas.parser.TextReader.__cinit__ (pandas/parser.c:4494) ValueError: No columns to parse from file 

Lo que es desconcertante, porque si ejecuto exactamente el mismo código con 'c.csv' lugar de c , el código funciona perfectamente. Además, si uso el siguiente fragmento de código:

 file = open('c.csv', 'w') file.write(c.getvalue()) 

El archivo CSV se guarda sin ningún problema, por lo que no es problema escribir en el objeto StringIO.

Es posible que deba reemplazar c con c.getvalue() en la línea read_csv, pero cuando lo hago, el intérprete intenta imprimir el contenido de c en el terminal. Seguramente hay una manera de evitar esto.

Gracias de antemano por la ayuda.

Hay dos problemas aquí, uno fundamental y uno que simplemente no ha encontrado todavía. : ^)

Primero, después de escribir en c , estás al final del archivo (virtual). Necesitas seek nuevo al inicio. Usaremos una cuadrícula más pequeña como ejemplo:

 >>> a = np.random.randint(0,256,(10,10)).astype('uint8') >>> b = pd.DataFrame(a) >>> c = StringIO() >>> b.to_csv(c, delimiter=' ', header=False, index=False) >>> next(c) Traceback (most recent call last): File "", line 1, in  next(c) StopIteration 

que genera el error “sin columnas”. Si seek primero, sin embargo:

 >>> c.seek(0) >>> next(c) '103,3,171,239,150,35,224,190,225,57\n' 

Pero ahora notarás el segundo problema … ¿comas? Pensé que habíamos solicitado delimitadores espaciales? Pero to_csv solo acepta sep , no delimiter . Me parece que debería aceptarlo u objetar que no lo hace, pero ignorarlo silenciosamente se siente como un error. De todos modos, si usamos sep (o delim_whitespace=True ):

 >>> a = np.random.randint(0,256,(10,10)).astype('uint8') >>> b = pd.DataFrame(a) >>> c = StringIO() >>> b.to_csv(c, sep=' ', header=False, index=False) >>> c.seek(0) >>> d = pd.read_csv(c, sep=' ', header=None, dtype='uint8') >>> d 0 1 2 3 4 5 6 7 8 9 0 209 65 218 242 178 213 187 63 137 145 1 161 222 50 92 157 31 49 62 218 30 2 182 255 146 249 115 91 160 53 200 252 3 192 116 87 85 164 46 192 228 104 113 4 89 137 142 188 183 199 106 128 110 1 5 208 140 116 50 66 208 116 72 158 169 6 50 221 82 235 16 31 222 9 95 111 7 88 36 204 96 186 205 210 223 22 235 8 136 221 98 191 31 174 83 208 226 150 9 62 93 168 181 26 128 116 92 68 153