2014-07-03 31 views
8

Tôi đang sử dụng gấu trúc để quản lý một mảng lớn các số nguyên 8 byte. Các số nguyên này được bao gồm dưới dạng các phần tử được phân cách bằng dấu cách của một cột trong tệp CSV được phân tách bằng dấu phẩy và kích thước mảng khoảng 10000x10000. Hình minh hoạgấu trúc không thể đọc từ đối tượng StringIO lớn

Pandas có thể đọc nhanh dữ liệu được phân cách bằng dấu phẩy từ một vài cột đầu tiên dưới dạng DataFrame và cũng nhanh chóng lưu trữ các chuỗi được phân cách bằng dấu cách trong một DataFrame khác. Sự cố xảy ra khi tôi cố gắng chuyển đổi bảng từ một cột các chuỗi được phân cách bằng dấu cách thành một DataFrame có số nguyên 8 bit.

Tôi đã thử những điều sau đây:

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

Nhưng việc sử dụng bộ nhớ là không thể chịu đựng - 10MB giá trị của số nguyên tiêu thụ 2GB bộ nhớ. Tôi nói rằng đó là một hạn chế của ngôn ngữ và không có gì tôi có thể làm về nó trong trường hợp này.

Như một giải pháp có thể xảy ra, tôi được khuyên nên lưu dữ liệu chuỗi vào tệp CSV và sau đó tải lại tệp CSV dưới dạng DataFrame của số nguyên được phân cách bằng dấu cách. Điều này làm việc tốt, nhưng để tránh sự chậm lại đến từ việc ghi vào đĩa, tôi đã thử viết một đối tượng StringIO.

Dưới đây là một tối thiểu không làm việc Ví dụ:

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

nào mang lại được thông báo lỗi sau:

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 

Đó là khó hiểu, bởi vì nếu tôi chạy mã chính xác cùng với 'c.csv' thay vì c , mã hoạt động hoàn hảo. Ngoài ra, nếu tôi sử dụng đoạn mã sau:

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

Tệp CSV được lưu mà không gặp bất kỳ sự cố nào, vì vậy việc ghi vào đối tượng StringIO không phải là vấn đề.

Có thể tôi cần phải thay thế c bằng c.getvalue() trong dòng read_csv, nhưng khi tôi làm điều đó, thông dịch viên cố gắng in nội dung của c trong thiết bị đầu cuối! Chắc chắn có một cách để giải quyết vấn đề này.

Cảm ơn bạn đã trợ giúp.

Trả lời

15

Có hai vấn đề ở đây, một vấn đề cơ bản và một vấn đề bạn chưa gặp phải. : ^)

Trước tiên, sau khi bạn viết thư cho c, bạn đang ở cuối tệp (ảo). Bạn cần phải seek quay lại phần đầu. Chúng tôi sẽ sử dụng lưới nhỏ hơn làm ví dụ:

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

tạo lỗi "không có cột". Nếu chúng tôi seek trước tiên, mặc dù:

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

Nhưng bây giờ bạn sẽ nhận thấy vấn đề thứ hai-- dấu phẩy? Tôi nghĩ rằng chúng tôi yêu cầu phân cách không gian? Nhưng to_csv chỉ chấp nhận sep, không phải delimiter. Dường như với tôi nó hoặc là chấp nhận nó hoặc đối tượng mà nó không, nhưng âm thầm bỏ qua nó cảm thấy giống như một lỗi.Dù sao, nếu chúng tôi sử dụng sep (hoặc 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 
+0

Cảm ơn câu trả lời tuyệt vời này. Tôi rất biết ơn. –

Các vấn đề liên quan