Mengindeks ulang file CSV besar

11

Saya telah memeriksa jawaban di utas bermanfaat ini , tetapi masalah saya tampaknya cukup berbeda sehingga saya tidak bisa memikirkan jawaban yang baik (setidaknya dengan sed).

Saya memiliki file CSV besar (200+ GB) dengan baris yang terlihat seperti berikut:

<alphanumerical_identifier>,<number>

di mana <alphanumerical_identifier>unik di seluruh file. Saya ingin membuat file terpisah yang menggantikan kolom pertama dengan indeks , yaitu

<index>,<number>

sehingga kita dapatkan:

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

Dapatkah awkmenghasilkan indeks yang meningkat tanpa memuat file lengkap dalam memori?

Karena indeks meningkat secara monoton, mungkin lebih baik jika hanya menjatuhkan indeks. Akankah solusi untuk itu berbeda ?, yaitu:

<number>
<number>
<number>
Amelio Vazquez-Reina
sumber
Saya tidak yakin tentang kelayakan solusi ini. Tapi bagaimana kalau hanya menghasilkan angka sebanyak dalam file CSV dalam file terpisah dan kemudian hanya menambahkan kolom kedua dari file CSV ke file itu?
Ramesh
@ Ramesh Itu tidak apa-apa asalkan outputnya benar.
Amelio Vazquez-Reina
2
Saya curiga saya salah paham tentang sesuatu; kalau tidak, awk -F, '{print ++n, $2}'akan berhasil. Atau awk -F, '{print $2}'untuk variasi kedua.
G-Man Mengatakan 'Reinstate Monica'
2
@ G-Man, itu mungkin itu meskipun FNRakan berfungsi sebaik++n
iruvar
1
Saya akan mengecek ulang bahwa Anda benar-benar dapat menyingkirkan Uniq Identifier itu ... mengapa tidak menambahkan kolom (3) pertama dengan indeks, tetapi masih menyimpan pengenalnya? bukankah pengenal itu digunakan di tempat lain?
Olivier Dulac

Jawaban:

13

Tidak dekat terminal untuk diuji, tetapi bagaimana dengan perintah yang sering diabaikan nl? Sesuatu seperti:

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

uskup
sumber
1
PS: File CSV 200GB ? Wow, dan saya pikir bekerja dengan Database Nomor Porting Amerika Utara sebagai CSV (beberapa DVD) sangat besar!
Uskup
1
Berhasil, meskipun ada kosong besar setelah nomor. Saya akan menggantinya dengan:cut -d, -f 2- /tmp/aa | nl -w 1 -p -s ,
Ángel
@ Angel: Terima kasih, perbarui jawaban saya untuk menggunakan opsi lebar -w 1alih-alih penomoran angka kiri.
Uskup
Thanks @bishop - Kemana perginya nama file input dan output?
Amelio Vazquez-Reina
1
@ user815423426 Ya, cutperintah sebelum simbol pipa ( |) akan memberi Anda hanya kolom kedua, yang secara efektif memiliki nomor baris tersirat.
Uskup
7

Berikut adalah beberapa pendekatan, tetapi tidak ada yang akan mendekati kecepatan cutdan nlsolusi di atas:

  1. awk

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

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

    atau

    perl -F, -ane '$F[0]=$.; print join ",", @F' file.csv
  3. Shell (tapi saya tidak merekomendasikannya untuk file 200G, ini akan memakan waktu lama)

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

Solusi di atas diurutkan dalam urutan kecepatan. Saya menguji pada laptop saya dan file 40M dan mereka mengambil (rata-rata 10 berjalan) 2.2282 (awk), 2.4555 (perl 1), 3.1825s (perl 2) dan 48.6035s kekalahan untuk shell. Solusi yang sangat cerdas cutdan nlsudah Anda miliki adalah sekitar 4 kali lebih cepat pada 0,6078.

terdon
sumber
Bagus, terima kasih untuk statistiknya! Hasil shell mengejutkan saya, agak. Jika Anda ganti printfdengan echo, apakah waktunya membaik secara signifikan?
Uskup
2
File 40G diproses dalam 2.2282 detik? Di mana saya bisa mendapatkan laptop itu untuk saya?
John B
2
@ JohnB umm, ya, maaf, itu 40M, bukan G :)
terdon
Saya suka pengaturan ulang $1pendekatan dengan awk. The cutsolusi pasti jauh lebih cepat, tapi itu yang diharapkan karena tidak menggantikan <alphanumerical_identifier>dengan apa pun. Saya pikir tercepat awkvarian mungkin sesuatu seperti: mawk 'BEGIN{FS=OFS=","}{$1=NR}1' file.csv > newfile.csv.
John B
@ JohnB ah, ya, saya akan menebak bahwa menggunakan OFSalih-alih mencetak secara eksplisit ,akan sedikit lebih cepat dan itu mungkin menambahkan hingga perbedaan yang signifikan dalam file besar.
terdon