String Python csv para matriz

187

Alguém conhece uma biblioteca ou função simples para analisar uma string codificada em csv e transformá-la em uma matriz ou dicionário?

Eu não acho que eu quero o módulo csv embutido , porque em todos os exemplos que vi que levam caminhos de arquivo, não seqüências de caracteres.

Drew LeSueur
fonte

Respostas:

259

Você pode converter uma string em um objeto de arquivo usando io.StringIOe depois passá-la para o csvmódulo:

from io import StringIO
import csv

scsv = """text,with,Polish,non-Latin,letters
1,2,3,4,5,6
a,b,c,d,e,f
gęś,zółty,wąż,idzie,wąską,dróżką,
"""

f = StringIO(scsv)
reader = csv.reader(f, delimiter=',')
for row in reader:
    print('\t'.join(row))

versão mais simples com split()novas linhas:

reader = csv.reader(scsv.split('\n'), delimiter=',')
for row in reader:
    print('\t'.join(row))

Ou você pode simplesmente split()essa sequência em linhas usando \ncomo separador e, em seguida, split()cada linha em valores, mas dessa forma você deve estar ciente de citar, portanto, csvé preferível usar o módulo.

No Python 2, você precisa importar StringIOcomo

from StringIO import StringIO

em vez de.

Michał Niklas
fonte
6
o método de divisão não iria funcionar se o seu arquivo CSV continha cordas que continham vírgulas
Carson Myers
3
ou cordas citado como valores (com ou sem vírgulas)
adamk
28
O Python 3 agora usa io.StringIO. (Esperemos que poupe um pouco de tempo os usuários do Python 3). então importe io e io.StringIO.
JStrahl
3
Em vez de .split('\n'), você pode usar .splitlines().
Denilson Sá Maia
1
Não, ele funciona muito bem com letras poloneses com Ogonki :-)
Michał Niklas
70

Simples - o módulo csv também funciona com listas:

>>> a=["1,2,3","4,5,6"]  # or a = "1,2,3\n4,5,6".split('\n')
>>> import csv
>>> x = csv.reader(a)
>>> list(x)
[['1', '2', '3'], ['4', '5', '6']]
adamk
fonte
4
É bom saber, mas lembre-se de que .split('\n')isso fará coisas estranhas se seus campos contiverem novas linhas.
Inaimathi 15/04
1
@Inaimathi, se for CSV, as novas linhas internas devem ser escapadas.
John La Rooy
As novas linhas não precisam ser escapadas se o campo estiver entre aspas.
Jonathan Stray
1
Essa funcionalidade não está bem documentada. Obrigado.
cowlinator
13

O documento oficial para csv.reader() https://docs.python.org/2/library/csv.html é muito útil, que diz

objetos de arquivo e objetos de lista são adequados

import csv

text = """1,2,3
a,b,c
d,e,f"""

lines = text.splitlines()
reader = csv.reader(lines, delimiter=',')
for row in reader:
    print('\t'.join(row))
soulmachine
fonte
11
>>> a = "1,2"
>>> a
'1,2'
>>> b = a.split(",")
>>> b
['1', '2']

Para analisar um arquivo CSV:

f = open(file.csv, "r")
lines = f.read().split("\n") # "\r\n" if needed

for line in lines:
    if line != "": # add other needed checks to skip titles
        cols = line.split(",")
        print cols
nvd
fonte
'Simples é melhor que complexo!'
Abdelouahab
9
-1 O problema com esta solução é que ela não leva em consideração "escape de string", ou seja, 3, "4,5,6, 6deve ser tratado como três campos em vez de cinco.
precisa saber é o seguinte
Simples, mas só funciona em alguns casos específicos, este não é o código CSV análise genérica
Christophe Roussy
8

Como outros já apontaram, o Python inclui um módulo para ler e gravar arquivos CSV. Funciona muito bem desde que os caracteres de entrada fiquem dentro dos limites ASCII. Caso você queira processar outras codificações, é necessário mais trabalho.

A documentação do Python para o módulo csv implementa uma extensão do csv.reader, que usa a mesma interface, mas pode lidar com outras codificações e retorna cadeias unicode. Basta copiar e colar o código da documentação. Depois disso, você pode processar um arquivo CSV como este:

with open("some.csv", "rb") as csvFile: 
    for row in UnicodeReader(csvFile, encoding="iso-8859-15"):
        print row
roskakori
fonte
Verifique se o arquivo Unicode não tem uma BOM (Byte Order Marcador)
Pierre
1
Sobre a BOM: O Python deve detectar e ignorar as BOMs oficiais em UTF-32, UTF-16 etc. Para ignorar a BOM não oficial da Microsoft para UTF-8, use 'utf-8-sig'como codec em vez de 'utf-8'.
Roskakori
7

De acordo com a documentação:

E embora o módulo não suporte diretamente a análise de seqüências de caracteres, isso pode ser feito facilmente:

import csv
for row in csv.reader(['one,two,three']):
    print row

Basta transformar sua string em uma lista de elementos únicos.

Importar o StringIO parece um pouco excessivo para mim quando este exemplo está explicitamente nos documentos.

roundar
fonte
2

Aqui está uma solução alternativa:

>>> import pyexcel as pe
>>> text="""1,2,3
... a,b,c
... d,e,f"""
>>> s = pe.load_from_memory('csv', text)
>>> s
Sheet Name: csv
+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
| a | b | c |
+---+---+---+
| d | e | f |
+---+---+---+
>>> s.to_array()
[[u'1', u'2', u'3'], [u'a', u'b', u'c'], [u'd', u'e', u'f']]

Aqui está a documentação

chfw
fonte
2

Use isso para ter um csv carregado em uma lista

import csv

csvfile = open(myfile, 'r')
reader = csv.reader(csvfile, delimiter='\t')
my_list = list(reader)
print my_list
>>>[['1st_line', '0'],
    ['2nd_line', '0']]
JimS
fonte
0

O Panda é uma biblioteca bastante poderosa e inteligente que lê CSV em Python

Um exemplo simples aqui, eu tenho o arquivo example.zip com quatro arquivos.

EXAMPLE.zip
 -- example1.csv
 -- example1.txt
 -- example2.csv
 -- example2.txt

from zipfile import ZipFile
import pandas as pd


filepath = 'EXAMPLE.zip'
file_prefix = filepath[:-4].lower()

zipfile = ZipFile(filepath)
target_file = ''.join([file_prefix, '/', file_prefix, 1 , '.csv'])

df = pd.read_csv(zipfile.open(target_file))

print(df.head()) # print first five row of csv
print(df[COL_NAME]) # fetch the col_name data

Depois de ter dados, você pode manipular para jogar com uma lista ou outros formatos.

webbyfox
fonte