2014-07-03 33 views
8

Çok sayıda 8 baytlık tamsayıları yönetmek için pandaları kullanıyorum. Bu tamsayılar virgülle ayrılmış bir CSV dosyasındaki bir sütunun boşlukla ayrılmış öğeleri olarak dahil edilir ve dizi boyutu yaklaşık 10000x10000'dür.pandalar büyük StringIO nesnesinden okunamayan pandalar

Pandalar, virgülle ayrılmış verileri ilk birkaç sütundan bir DataFrame olarak hızlı bir şekilde okuyabilir ve ayrıca alanla sınırlanmış dizeleri başka bir DataFrame'de hızlı bir şekilde en az güçlükle depolayabilir. Sorun, tabloyu, tek bir boşlukla ayrılmış dizelerden oluşan bir kolondan 8 bitlik tamsayıların DataFrame'ine dönüştürmeye çalıştığımda ortaya çıkıyor. tamsayılar 10MB değerinde 2GB bellek tüketir -

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

Ama bellek kullanımı dayanılmaz:

Aşağıdaki çalıştılar. Bu dilin bir sınırlaması olduğunu ve bu durumda bunun hakkında yapabileceğim hiçbir şey olmadığı söylendi.

Olası bir geçici çözüm olarak, dize verilerini bir CSV dosyasına kaydetmesi ve ardından CSV dosyasını alanla sınırlı tamsayıların bir DataFrame'i olarak yeniden yüklemesi tavsiye edildi. Bu iyi çalışıyor, ancak disketten diske gelen yavaşlamayı önlemek için bir StringIO nesnesine yazmayı denedim. aşağıdaki hata iletisini verir

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

: Burada

minimal olmayan çalışma örneği, çözmeye çalıştığı

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 

Ben 'c.csv' yerine c ile tam aynı kod çalıştırmasına çünkü eğer , kod mükemmel çalışıyor. Aşağıdaki parçacığını kullanırsanız Ayrıca:

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

CSV dosyası böylece StringIO nesnesine yazma, herhangi bir sorun olmadan kaydedilmesini sorun değildir.

Ben read_csv hattında c.getvalue() ile c değiştirmeniz gerekiyor mümkündür, ama bunu yaparken, tercüman Terminalde c içeriğini yazdırmak için çalışır! Elbette bu konuda çalışmanın bir yolu var.

Yardım için şimdiden teşekkür ederiz.

cevap

15

Buradaki iki konu var, bir tanesi basit ve henüz rastlamadınız. : ^)

İlk olarak, c'a yazdıktan sonra (sanal) dosyanın sonundasınız. Başlamak için seek geri gerekir. Biz örnek olarak daha küçük bir ızgara kullanacağız: "hayır sütun" hata üretir

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

.

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

Ama şimdi ikinci issue-- virgül fark edeceksiniz: Eğer biz de, ilk seek? Uzay sınırlayıcıları istediğimizi sanıyordum? Ancak to_csv yalnızca delimiter değil sep kabul eder. Bana öyle geliyor ya kabul etmeli ya da itiraz etmiyor, ama sessizce görmezden gelmek bir böcek gibi geliyor.Biz sep (veya delim_whitespace=True) kullanırsanız Neyse,:

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

bu mükemmel yanıt için teşekkür ederiz. Çok müteşekkirim. –