Como leio dados CSV em uma matriz de registros no NumPy?

414

Gostaria de saber se existe uma maneira direta para importar o conteúdo de um arquivo CSV em uma matriz disco, muito na maneira que de R read.table(), read.delim()e read.csv()as importações familiares de dados para quadro de dados do R?

Ou é a melhor maneira de usar csv.reader () e aplicar algo como numpy.core.records.fromrecords()?

hatmatrix
fonte
Possível duplicata de Como ler e gravar arquivos CSV com Python?
Martin Thoma

Respostas:

646

Você pode usar o genfromtxt()método do Numpy para isso, definindo o delimiterkwarg como vírgula.

from numpy import genfromtxt
my_data = genfromtxt('my_file.csv', delimiter=',')

Mais informações sobre a função podem ser encontradas na respectiva documentação .

Andrew
fonte
10
E se você quiser algo de tipos diferentes? Como strings e ints?
CGTheLegend
11
@CGTheLegend np.genfromtxt ('myfile.csv', delimitador = ',', dtype = None)
chickensoup
2
numpy.loadtxt funcionou muito bem para mim também
Yibo Yang
10
Eu tentei isso, mas só estou obtendo nanvalores, por quê? Também com loadtxt, estou recebendo UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 155: ordinal not in range(128). Eu tenho tremas como ä e ö nos dados de entrada.
hhh
1
@hhh tente adicionar encoding="utf8"argumento. O Python é uma das poucas peças de software modernas que freqüentemente causam problemas de codificação de texto, que parecem coisas do passado.
Kolen
187

Eu recomendaria a read_csvfunção da pandasbiblioteca:

import pandas as pd
df=pd.read_csv('myfile.csv', sep=',',header=None)
df.values
array([[ 1. ,  2. ,  3. ],
       [ 4. ,  5.5,  6. ]])

Isso fornece um DataFrame do pandas - permitindo muitas funções úteis de manipulação de dados que não estão diretamente disponíveis com matrizes de registros numpy .

DataFrame é uma estrutura de dados rotulada bidimensional com colunas de tipos potencialmente diferentes. Você pode pensar nisso como uma planilha ou tabela SQL ...


Eu também recomendaria genfromtxt. No entanto, como a pergunta solicita uma matriz de registros , em oposição a uma matriz normal, o dtype=Noneparâmetro precisa ser adicionado à genfromtxtchamada:

Dado um arquivo de entrada, myfile.csv:

1.0, 2, 3
4, 5.5, 6

import numpy as np
np.genfromtxt('myfile.csv',delimiter=',')

dá uma matriz:

array([[ 1. ,  2. ,  3. ],
       [ 4. ,  5.5,  6. ]])

e

np.genfromtxt('myfile.csv',delimiter=',',dtype=None)

fornece uma matriz de registros:

array([(1.0, 2.0, 3), (4.0, 5.5, 6)], 
      dtype=[('f0', '<f8'), ('f1', '<f8'), ('f2', '<i4')])

Isso tem a vantagem de que arquivos com vários tipos de dados (incluindo cadeias) podem ser facilmente importados .

atomh33ls
fonte
O read_csv trabalha com vírgulas entre aspas. Recomendo este genfromtxt sobre
Viet
3
usar cabeçalho = 0 para ignorar a primeira linha nos valores, se o arquivo tem um cabeçalho 1-line
c-chavez
Lembre-se de que isso cria uma matriz 2D: por exemplo (1000, 1). np.genfromtxtnão faz isso: por exemplo (1000,).
Newskooler
74

Eu cronometrei o

from numpy import genfromtxt
genfromtxt(fname = dest_file, dtype = (<whatever options>))

versus

import csv
import numpy as np
with open(dest_file,'r') as dest_f:
    data_iter = csv.reader(dest_f,
                           delimiter = delimiter,
                           quotechar = '"')
    data = [data for data in data_iter]
data_array = np.asarray(data, dtype = <whatever options>)

em 4,6 milhões de linhas com cerca de 70 colunas e constatou que o caminho do NumPy levou 2 minutos e 16 segundos e o método de compreensão da lista csv levou 13 segundos.

Eu recomendaria o método de compreensão da lista csv, pois ele provavelmente depende de bibliotecas pré-compiladas e não do intérprete tanto quanto do NumPy. Eu suspeito que o método dos pandas teria uma sobrecarga de intérprete semelhante.

William komp
fonte
23
Testei código semelhante a este com um arquivo csv contendo 2,6 milhões de linhas e 8 colunas. numpy.recfromcsv () demorou cerca de 45 segundos, np.asarray (list (csv.reader ())) demorou cerca de 7 segundos e pandas.read_csv () demorou cerca de 2 segundos (!). (O arquivo foi lido recentemente do disco em todos os casos, portanto já estava no cache de arquivos do sistema operacional.) Acho que vou com os pandas.
Matthias Fripp
5
Acabei de notar que há algumas notas sobre o design do analisador csv rápido do pandas em wesmckinney.com/blog/… . O autor leva muito a sério os requisitos de velocidade e memória. Também é possível usar as_recarray = True para obter o resultado diretamente como uma matriz de registros Python, em vez de um dataframe do pandas.
Matthias Fripp
67

Você também pode tentar recfromcsv()adivinhar os tipos de dados e retornar uma matriz de registros formatada corretamente.

btel
fonte
9
Se você deseja manter os nomes dos pedidos / colunas no CSV, pode usar a seguinte chamada: numpy.recfromcsv(fname, delimiter=',', filling_values=numpy.nan, case_sensitive=True, deletechars='', replace_space=' ')Os principais argumentos são os três últimos.
eacousineau
16

Como tentei nos dois sentidos usando o NumPy e o Pandas, o uso de pandas tem muitas vantagens:

  • Mais rápido
  • Menos uso da CPU
  • Uso de 1/3 de RAM em comparação com o NumPy genfromtxt

Este é o meu código de teste:

$ for f in test_pandas.py test_numpy_csv.py ; do  /usr/bin/time python $f; done
2.94user 0.41system 0:03.05elapsed 109%CPU (0avgtext+0avgdata 502068maxresident)k
0inputs+24outputs (0major+107147minor)pagefaults 0swaps

23.29user 0.72system 0:23.72elapsed 101%CPU (0avgtext+0avgdata 1680888maxresident)k
0inputs+0outputs (0major+416145minor)pagefaults 0swaps

test_numpy_csv.py

from numpy import genfromtxt
train = genfromtxt('/home/hvn/me/notebook/train.csv', delimiter=',')

test_pandas.py

from pandas import read_csv
df = read_csv('/home/hvn/me/notebook/train.csv')

Arquivo de dados:

du -h ~/me/notebook/train.csv
 59M    /home/hvn/me/notebook/train.csv

Com NumPy e pandas nas versões:

$ pip freeze | egrep -i 'pandas|numpy'
numpy==1.13.3
pandas==0.20.2
HVNSweeting
fonte
5

Você pode usar esse código para enviar dados do arquivo CSV para uma matriz:

import numpy as np
csv = np.genfromtxt('test.csv', delimiter=",")
print(csv)
chamzz.dot
fonte
4

Usando numpy.loadtxt

Um método bastante simples. Mas exige que todos os elementos sejam flutuados (int e assim por diante)

import numpy as np 
data = np.loadtxt('c:\\1.csv',delimiter=',',skiprows=0)  
Xiaojian Chen
fonte
4

Esta é a maneira mais fácil:

import csv with open('testfile.csv', newline='') as csvfile: data = list(csv.reader(csvfile))

Agora, cada entrada nos dados é um registro, representado como uma matriz. Então você tem uma matriz 2D. Isso me salvou muito tempo.

Matthew Park
fonte
Por que deveríamos ter que mexer com o Pandas, quando essas ferramentas têm muito menos recursos inchados?
Christopher
3

Eu tentei isso:

import pandas as p
import numpy as n

closingValue = p.read_csv("<FILENAME>", usecols=[4], dtype=float)
print(closingValue)
muTheTechie
fonte
3

Eu sugeriria o uso de tables ( pip3 install tables). Você pode salvar seu .csvarquivo .h5usando pandas ( pip3 install pandas),

import pandas as pd
data = pd.read_csv("dataset.csv")
store = pd.HDFStore('dataset.h5')
store['mydata'] = data
store.close()

Você pode facilmente, e com menos tempo, mesmo para uma enorme quantidade de dados, carregar seus dados em uma matriz NumPy .

import pandas as pd
store = pd.HDFStore('dataset.h5')
data = store['mydata']
store.close()

# Data in NumPy format
data = data.values
Jatin Mandav
fonte
3

Este trabalho como um encanto ...

import csv
with open("data.csv", 'r') as f:
    data = list(csv.reader(f, delimiter=";"))

import numpy as np
data = np.array(data, dtype=np.float)
Nihal Sargaiya
fonte
o código precisa ser recuado adequadamente dentro de seu layout de marcação de código.
precisa saber é o seguinte