Reindexando um arquivo CSV grande

11

Analisei as respostas neste tópico útil , mas meu problema parece ser diferente o suficiente para que eu não consiga pensar em uma boa resposta (pelo menos com sed).

Eu tenho um arquivo CSV grande (mais de 200 GB) com linhas parecidas com a seguinte:

<alphanumerical_identifier>,<number>

onde <alphanumerical_identifier>é único em todo o arquivo. Eu gostaria de criar um arquivo separado que substitua a primeira coluna por um índice , ou seja,

<index>,<number>

para que possamos obter:

1, <number>
2, <number>
3, <number>

Pode awkgerar um índice crescente sem carregar o arquivo completo na memória?

Como o índice aumenta monotonicamente, pode ser ainda melhor simplesmente descartá-lo. A solução para isso seria tão diferente ?, ou seja:

<number>
<number>
<number>
Amelio Vazquez-Reina
fonte
Não tenho certeza da viabilidade desta solução. Mas que tal apenas gerar tantos números quanto no arquivo CSV em um arquivo separado e anexar a segunda coluna do arquivo CSV a esse arquivo?
Ramesh
@ Jamesh Isso está perfeitamente bem desde que a saída esteja correta.
Amelio Vazquez-Reina
2
Eu suspeito que estou entendendo mal alguma coisa; caso contrário, awk -F, '{print ++n, $2}'funcionaria. Ou awk -F, '{print $2}'para a segunda variação.
G-Man diz 'Reinstate Monica'
2
@ G-Man, é provavelmente isso, embora FNRsirva tão bem quanto++n
#
1
Eu verificaria três vezes se você realmente pode se livrar desse identificador Uniq ... por que não adicionar uma primeira (terceira) coluna ao índice, mas ainda assim manter o identificador? esse identificador não é usado em outro lugar ?
Olivier Dulac

Respostas:

13

Não é perto de um terminal para testar, mas e o nlcomando muitas vezes esquecido ? Algo como:

cut -f 2 -d , original.csv | nl -w 1 -p -s , > numbered.csv

bispo
fonte
1
PS: Um arquivo CSV de 200 GB ? Uau, e eu pensei que trabalhar com o banco de dados de números portados da América do Norte como um CSV (um par de DVD) era enorme!
bispo
1
Funciona, embora exista um grande espaço em branco após o número. Eu o substituiria por:cut -d, -f 2- /tmp/aa | nl -w 1 -p -s ,
Ángel
@ Angel: Obrigado, atualizei minha resposta para usar a opção de largura em -w 1vez de numeração à esquerda.
bispo
Thanks @bishop - Para onde vão os nomes dos arquivos de entrada e saída?
Amelio Vazquez-Reina
1
@ user815423426 Sim, o cutcomando antes do símbolo de barra vertical ( |) fornecerá apenas a segunda coluna, com números de linhas implícitos.
bispo
7

Aqui estão algumas abordagens, mas nenhuma abordará a velocidade da solução cute nlacima:

  1. awk

    awk -F, '{$1=NR;print $1","$2;}' file.csv > newfile.csv
  2. Perl

    perl -pe 's/[^,]+/$./' file.csv > newfile.csv

    ou

    perl -F, -ane '$F[0]=$.; print join ",", @F' file.csv
  3. Shell (mas eu não o recomendo para um arquivo 200G, isso levará séculos)

    i=1; while IFS=, read foo num; do 
            printf "%d,%s\n" $((i++)) $num; 
    done < file.csv > newfile.csv

As soluções acima são classificadas em ordem de velocidade. Eu testei no meu laptop e um arquivo de 40M e eles tiraram (média de 10 execuções) 2,22282 (awk), 2,4555 (1º perl), 3,1825s (2º perl) e um impressionante 48.6035s para o shell. A solução cute a nlsolução mais inteligentes que você já possui foram cerca de 4 vezes mais rápidas a 0,6078s.

terdon
fonte
Bom, obrigado pelas estatísticas! O resultado da concha me surpreende um pouco. Se você substituir printfpor echo, o tempo melhora significativamente?
bispo
2
Arquivo 40G processado em 2.2282 segundos? Onde posso conseguir esse laptop para mim?
John B,
2
@JohnB umm, sim, desculpe, que era 40M, não G :)
terdon
Eu gosto da redefinição da $1abordagem com awk. A cutsolução é definitivamente muito mais rápida, mas é de se esperar, pois não substitui <alphanumerical_identifier>por nada. Eu acho que o mais rápido awkvariante poderia ser algo como: mawk 'BEGIN{FS=OFS=","}{$1=NR}1' file.csv > newfile.csv.
John B,
@ JohnB ah, sim, eu acho que usar em OFSvez de imprimir explicitamente ,seria um pouco mais rápido e isso pode resultar em uma diferença significativa em arquivos grandes.
terdon