pandas не удается прочитать из большого объекта StringIO
Я использую pandas для управления большим массивом 8-байтовых целых чисел. Эти целые числа включаются в качестве разделенных пробелами элементов столбца в CSV-файл с разделителями-запятыми, а размер массива составляет около 10000x10000.
Pandas может быстро читать данные с разделителями-запятыми из первых нескольких столбцов в качестве фрейма данных, а также быстро хранить строки с разделителями-пробелами в другом фрейме данных с минимальными хлопотами. Беда приходит, когда я пытаюсь бросить, превратить стол из одного столбец строк, разделенных пробелами, для фрейма данных из 8-разрядных целых чисел.
я попробовал следующее:
intdata = pd.DataFrame(strdata.columnname.str.split().tolist(), dtype='uint8')
но использование памяти невыносимо-10 МБ целых чисел потребляет 2 ГБ памяти. Мне сказали, что это ограничение языка, и я ничего не могу с этим поделать.
в качестве возможного обходного пути мне посоветовали сохранить строковые данные в CSV-файл, а затем перезагрузить CSV-файл как фрейм данных целых чисел с пробелами. Это хорошо работает, но чтобы избежать замедления записи на диск, я попытался написать объект StringIO.
вот минимальный нерабочий пример:
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')
, который дает следующее сообщение об ошибке:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
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
что вызывает недоумение, потому что если я запускаю тот же код 'c.csv'
вместо c
, код работает отлично. Кроме того, если я использую следующий фрагмент:
file = open('c.csv', 'w')
file.write(c.getvalue())
файл CSV сохраняется без каких-либо проблем, поэтому запись в объект StringIO не является проблемой.
возможно, что мне нужно заменить c
С c.getvalue()
в строке read_csv, но когда я это делаю, интерпретатор пытается распечатать содержимое c
в терминале! Конечно, есть способ обойти это.
заранее спасибо за помощь.
1 ответов
здесь есть два вопроса, один фундаментальный и один, с которым вы просто еще не сталкивались. :^)
во-первых, после того, как вы напишите c
, вы находитесь в конце (виртуального) файла. Вам нужно seek
вернуться к началу. В качестве примера мы будем использовать меньшую сетку:
>>> 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 "<ipython-input-57-73b012f9653f>", line 1, in <module>
next(c)
StopIteration
который генерирует ошибку" нет столбцов". Если мы ... --4--> во-первых, хотя:
>>> c.seek(0)
>>> next(c)
'103,3,171,239,150,35,224,190,225,57\n'
но теперь вы заметите второй вопрос -- запятые? Я думал, нам нужно место. разделители? Но!--6--> только sep
, а не delimiter
. Мне кажется, он должен либо принять это, либо возразить, что это не так, но молча игнорировать это похоже на ошибку. Во всяком случае, если мы используем sep
(или 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