Despejar uma matriz NumPy em um arquivo csv

545

Existe uma maneira de despejar uma matriz NumPy em um arquivo CSV? Eu tenho uma matriz NumPy 2D e preciso despejá-la em formato legível por humanos.

Dexter
fonte

Respostas:

867

numpy.savetxt salva uma matriz em um arquivo de texto.

import numpy
a = numpy.asarray([ [1,2,3], [4,5,6], [7,8,9] ])
numpy.savetxt("foo.csv", a, delimiter=",")
Jim Brissom
fonte
2
isso é preferível a loop através da matriz por dimensão? Eu acho que sim.
Ehtesh Choudhury
51
você também pode alterar o formato de cada figura com a palavra-chave fmt. o padrão é '% .18e', pode ser difícil de ler, você pode usar '% .3e' para exibir apenas 3 casas decimais.
Andrea Zonca
3
Andrea, sim, usei% 10,5f. Foi bem conveniente.
Dexter
12
Seu método funciona bem para dados numéricos, mas gera um erro para numpy.arrayde strings. Você poderia prescrever um método para salvar como csv para um numpy.arrayobjeto contendo seqüências de caracteres?
EBE Isaac
16
@ ÉbeIsaac Você também pode especificar o formato da string:fmt='%s'
Luis
137

Você pode usar pandas. É preciso alguma memória extra, portanto nem sempre é possível, mas é muito rápido e fácil de usar.

import pandas as pd 
pd.DataFrame(np_array).to_csv("path/to/file.csv")

se você não quiser um cabeçalho ou índice, use to_csv("/path/to/file.csv", header=None, index=None)

maxbellec
fonte
4
No entanto, isso também escreverá um índice de coluna na primeira linha.
RM
5
@ RM- você pode usardf.to_csv("file_path.csv", header=None)
maxbellec
4
Não é bom. Isso cria um df e consome memória extra por nada #
317 Tex
20
funcionou como um encanto, é muito rápido - uma troca para uso extra de memória. Os parâmetros header=None, index=Noneremovem a linha do cabeçalho e a coluna do índice.
thepunitsingh
3
@DaveC: você deve definir o commentsargumento da palavra - chave como '', o #será suprimido.
Milind R
46

tofile é uma função conveniente para fazer isso:

import numpy as np
a = np.asarray([ [1,2,3], [4,5,6], [7,8,9] ])
a.tofile('foo.csv',sep=',',format='%10.5f')

A página do manual tem algumas notas úteis:

Esta é uma função de conveniência para armazenamento rápido de dados da matriz. As informações sobre endianness e precisão são perdidas; portanto, esse método não é uma boa opção para arquivos destinados a arquivar dados ou transportar dados entre máquinas com endianness diferente. Alguns desses problemas podem ser superados com a saída dos dados como arquivos de texto, à custa da velocidade e do tamanho do arquivo.

Nota. Esta função não produz arquivos CSV de várias linhas, salva tudo em uma linha.

atomh33ls
fonte
5
Tanto quanto posso dizer, isso não produz um arquivo CSV, mas coloca tudo em uma única linha.
Peter
@ Peter, bom ponto, obrigado, eu atualizei a resposta. Para mim, ele salva ok no formato csv (embora limitado a uma linha). Além disso, está claro que a intenção do solicitante é "despejá-lo em formato legível por humanos" - então acho que a resposta é relevante e útil.
atomh33ls
6
Desde a versão 1.5.0, o np.tofile () usa um parâmetro opcional newline = '\ n' para permitir saída em várias linhas. docs.scipy.org/doc/numpy-1.13.0/reference/generated/…
Kevin J. Black
2
Na verdade, np.savetext () fornece o argumento de nova linha, não np.tofile ()
eaydin
14

Escrever matrizes de registro como arquivos CSV com cabeçalhos requer um pouco mais de trabalho.

Este exemplo lê um arquivo CSV com o cabeçalho na primeira linha e depois grava o mesmo arquivo.

import numpy as np

# Write an example CSV file with headers on first line
with open('example.csv', 'w') as fp:
    fp.write('''\
col1,col2,col3
1,100.1,string1
2,222.2,second string
''')

# Read it as a Numpy record array
ar = np.recfromcsv('example.csv')
print(repr(ar))
# rec.array([(1, 100.1, 'string1'), (2, 222.2, 'second string')], 
#           dtype=[('col1', '<i4'), ('col2', '<f8'), ('col3', 'S13')])

# Write as a CSV file with headers on first line
with open('out.csv', 'w') as fp:
    fp.write(','.join(ar.dtype.names) + '\n')
    np.savetxt(fp, ar, '%s', ',')

Observe que este exemplo não considera seqüências de caracteres com vírgulas. Para considerar cotações para dados não numéricos, use o csvpacote:

import csv

with open('out2.csv', 'wb') as fp:
    writer = csv.writer(fp, quoting=csv.QUOTE_NONNUMERIC)
    writer.writerow(ar.dtype.names)
    writer.writerows(ar.tolist())
Mike T
fonte
É aqui que os pandas novamente ajudam. Você pode fazer: pd.DataFrame (fora, colunas = ['col1', 'col2'])), etc
EFreak
10

Como já discutido, a melhor maneira de despejar a matriz em um arquivo CSV é usando .savetxt(...) método No entanto, há certas coisas que devemos saber para fazê-lo corretamente.

Por exemplo, se você tiver uma matriz numpy com dtype = np.int32o

   narr = np.array([[1,2],
                 [3,4],
                 [5,6]], dtype=np.int32)

e deseja salvar usando savetxtcomo

np.savetxt('values.csv', narr, delimiter=",")

Ele armazenará os dados no formato exponencial de ponto flutuante como

1.000000000000000000e+00,2.000000000000000000e+00
3.000000000000000000e+00,4.000000000000000000e+00
5.000000000000000000e+00,6.000000000000000000e+00

Você precisará alterar a formatação usando um parâmetro chamado fmtcomo

np.savetxt('values.csv', narr, fmt="%d", delimiter=",")

para armazenar dados em seu formato original

Salvando dados no formato compactado gz

Além disso, savetxtpode ser usado para armazenar dados em .gzformato compactado, o que pode ser útil durante a transferência de dados pela rede.

Só precisamos alterar a extensão do arquivo, pois o .gznumpy cuidará de tudo automaticamente

np.savetxt('values.gz', narr, fmt="%d", delimiter=",")

Espero que ajude

Daksh
fonte
1
A fmt="%d"era o que eu estava procurando. Obrigado!
Payne
6

Acredito que você também pode fazer isso da seguinte maneira:

  1. Converter array Numpy em um dataframe do Pandas
  2. Salvar como CSV

por exemplo, nº 1:

    # Libraries to import
    import pandas as pd
    import nump as np

    #N x N numpy array (dimensions dont matter)
    corr_mat    #your numpy array
    my_df = pd.DataFrame(corr_mat)  #converting it to a pandas dataframe

por exemplo, nº 2:

    #save as csv 
    my_df.to_csv('foo.csv', index=False)   # "foo" is the name you want to give
                                           # to csv file. Make sure to add ".csv"
                                           # after whatever name like in the code
DrDEE
fonte
5

se você deseja escrever na coluna:

    for x in np.nditer(a.T, order='C'): 
            file.write(str(x))
            file.write("\n")

Aqui 'a' é o nome da matriz numpy e 'file' é a variável a ser gravada em um arquivo.

Se você deseja escrever em linha:

    writer= csv.writer(file, delimiter=',')
    for x in np.nditer(a.T, order='C'): 
            row.append(str(x))
    writer.writerow(row)
Rimjhim.
fonte
2

Se você quiser salvar seu array numpy (por exemplo your_array = np.array([[1,2],[3,4]])) em uma célula, poderá convertê-lo primeiro comyour_array.tolist() .

Em seguida, salve-o da maneira normal em uma célula, com delimiter=';' e a célula no arquivo csv ficará assim[[1, 2], [2, 4]]

Então você pode restaurar sua matriz assim: your_array = np.array(ast.literal_eval(cell_string))

Mr Poin
fonte
bem que é, literalmente, vai destruir todas as economias de memória para o uso de uma matriz numpy
PirateApp
2

Você também pode fazer isso com python puro sem usar nenhum módulo.

# format as a block of csv text to do whatever you want
csv_rows = ["{},{}".format(i, j) for i, j in array]
csv_text = "\n".join(csv_rows)

# write it to a file
with open('file.csv', 'w') as f:
    f.write(csv_text)
Greg
fonte
1
Isso usa muita memória . Prefira fazer o loop sobre cada linha, formate e escreva.
Remram 2/17
@remram isso depende de seus dados, mas sim se é grande ele pode usar uma grande quantidade de memória
Greg
2

No Python, usamos o módulo csv.writer () para gravar dados em arquivos csv. Este módulo é semelhante ao módulo csv.reader ().

import csv

person = [['SN', 'Person', 'DOB'],
['1', 'John', '18/1/1997'],
['2', 'Marie','19/2/1998'],
['3', 'Simon','20/3/1999'],
['4', 'Erik', '21/4/2000'],
['5', 'Ana', '22/5/2001']]

csv.register_dialect('myDialect',
delimiter = '|',
quoting=csv.QUOTE_NONE,
skipinitialspace=True)

with open('dob.csv', 'w') as f:
    writer = csv.writer(f, dialect='myDialect')
    for row in person:
       writer.writerow(row)

f.close()

Um delimitador é uma sequência usada para separar campos. O valor padrão é vírgula (,).

Tamil Selvan S
fonte
Isso já foi sugerido: stackoverflow.com/a/41009026/8881141 Adicione apenas novas abordagens, não repita as sugestões publicadas anteriormente.
Mr. T