web-dev-qa-db-fra.com

pandas.read_csv à partir de données de chaîne ou de package

J'ai des données texte csv dans un paquet que je veux lire en utilisant read_csv. Je faisais ça en

from pkgutil import get_data
from StringIO import StringIO

data = read_csv(StringIO(get_data('package.subpackage', 'path/to/data.csv')))

Cependant, StringIO.StringIO disparaît dans Python 3, et io.StringIO accepte uniquement Unicode. Existe-t-il un moyen simple de le faire?

Modifier : ce qui suit ne semble pas fonctionner

import pandas as pd

import pkgutil
from io import StringIO

def get_data_file(pkg, path):
    f = StringIO()
    contents = unicode(pkgutil.get_data('pymc.examples', 'data/wells.dat'))
    f.write(contents)
    return f

wells = get_data_file('pymc.examples', 'data/wells.dat')

data = pd.read_csv(wells, delimiter=' ', index_col='id',
                   dtype={'switch': np.int8})

échouer avec

  File "/usr/local/lib/python2.7/dist-packages/pandas/io/parsers.py", line 401, in parser_f
    return _read(filepath_or_buffer, kwds)
  File "/usr/local/lib/python2.7/dist-packages/pandas/io/parsers.py", line 209, in _read
    parser = TextFileReader(filepath_or_buffer, **kwds)
  File "/usr/local/lib/python2.7/dist-packages/pandas/io/parsers.py", line 509, in __init__
    self._make_engine(self.engine)
  File "/usr/local/lib/python2.7/dist-packages/pandas/io/parsers.py", line 611, in _make_engine
    self._engine = CParserWrapper(self.f, **self.options)
  File "/usr/local/lib/python2.7/dist-packages/pandas/io/parsers.py", line 893, in __init__
    self._reader = _parser.TextReader(src, **kwds)
  File "parser.pyx", line 441, in pandas._parser.TextReader.__cinit__ (pandas/src/parser.c:3940)
  File "parser.pyx", line 551, in pandas._parser.TextReader._get_header (pandas/src/parser.c:5096)
pandas._parser.CParserError: Passed header=0 but only 0 lines in file
25
John Salvatier

Ce qui suit a fonctionné pour moi en 3.3:

>>> import numpy as np, pandas as pd
>>> import io, pkgutil
>>> wells = pkgutil.get_data('pymc.examples', 'data/wells.dat')
>>> type(wells)
<class 'bytes'>
>>> df = pd.read_csv(io.BytesIO(wells), encoding='utf8', sep=" ", index_col="id", dtype={"switch": np.int8})
>>> df.head()
    switch  arsenic       dist  assoc  educ
id                                         
1        1     2.36  16.826000      0     0
2        1     0.71  47.321999      0     0
3        0     2.07  20.966999      0    10
4        1     1.15  21.486000      0    12
5        1     1.10  40.874001      1    14

[5 rows x 5 columns]

N.B. J'ai dû mettre manuellement wells.dat à cet endroit, donc je ne peux pas jurer que je l'ai copié correctement et qu'il n'y a pas d'espaces terminaux, car j'en ai supprimé certains. Mais en passant read_csv un objet BytesIO et un paramètre de codage devraient fonctionner. (En fait, vous pouvez probablement vous en passer, mais c'est une bonne habitude. io.TextIOWrapper pourrait être une autre option.)

32
DSM

Pour passer un string à pandas read_csv() , vous pouvez utiliser io.StringIO , c'est-à-dire:

import pandas as pd
from io import StringIO
df = pd.read_csv(StringIO("csv string..."))
27
Pedro Lobito