Reindexar un archivo CSV grande

11

Revisé las respuestas en este útil hilo , pero mi problema parece ser lo suficientemente diferente como para no pensar en una buena respuesta (al menos con sed).

Tengo un archivo CSV grande (más de 200 GB) con filas que se parecen a lo siguiente:

<alphanumerical_identifier>,<number>

donde <alphanumerical_identifier>es único en todo el archivo. Me gustaría crear un archivo separado que reemplace la primera columna por un índice , es decir

<index>,<number>

para que obtengamos:

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

¿Puede awkgenerar un índice creciente sin cargar el archivo completo en la memoria?

Dado que el índice aumenta monotónicamente, puede ser aún mejor simplemente dejar caer el índice. ¿Sería la solución para eso tan diferente ?, es decir:

<number>
<number>
<number>
Amelio Vazquez-Reina
fuente
No estoy seguro de la viabilidad de esta solución. Pero, ¿qué tal simplemente generar tantos números como en el archivo CSV en un archivo separado y luego simplemente agregar la segunda columna del archivo CSV a ese archivo?
Ramesh
@Ramesh Eso está perfectamente bien siempre que la salida sea correcta.
Amelio Vazquez-Reina
2
Sospecho que estoy malentendiendo algo; de lo contrario, awk -F, '{print ++n, $2}'funcionaría. O awk -F, '{print $2}'para la segunda variación.
G-Man dice 'reinstalar a Monica' el
2
@ G-Man, eso es probablemente, aunque FNRserviría tan bien como++n
iruvar
1
Verificaría tres veces que realmente puedas deshacerte de ese Identificador Uniq ... ¿por qué no agregar una primera (3ra) columna con el índice, pero aún así mantener el identificador? ¿No se usa ese identificador en otro lugar ?
Olivier Dulac

Respuestas:

13

No cerca de una terminal para probar, pero ¿qué tal el nlcomando que a menudo se pasa por alto ? Algo como:

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

obispo
fuente
1
PD: ¿Un archivo CSV de 200 GB ? ¡Guau, y pensé que trabajar con la Base de datos de números portados de América del Norte como CSV (un par de DVD) fue enorme!
obispo
1
Funciona, aunque hay un gran espacio en blanco después del número. Lo reemplazaría con:cut -d, -f 2- /tmp/aa | nl -w 1 -p -s ,
Ángel
@ Angel: Gracias, actualicé mi respuesta para usar la opción de ancho en -w 1lugar de la numeración izquierda.
obispo
Gracias @bishop - ¿A dónde van los nombres de archivo de entrada y salida?
Amelio Vazquez-Reina
1
@ user815423426 Sí, el cutcomando antes del símbolo de canalización ( |) le dará solo la segunda columna, con números de línea implícitos.
obispo
7

Aquí hay algunos enfoques, pero ninguno se acercará a la velocidad de la cuty la nlsolución anterior:

  1. awk

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

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

    o

    perl -F, -ane '$F[0]=$.; print join ",", @F' file.csv
  3. Shell (pero no lo recomiendo para un archivo de 200G, llevará años)

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

Las soluciones anteriores se ordenan por orden de velocidad. Probé en mi computadora portátil y un archivo de 40M y tomaron (promedio de 10 ejecuciones) 2.2282 (awk), 2.4555 (1er perl), 3.1825s (2do perl) y la friolera de 48.6035s para el shell. El muy inteligente cuty nlsolución ya tiene fue alrededor de 4 veces más rápido en 0.6078s.

terdon
fuente
Bien, gracias por las estadísticas! El resultado del shell me sorprende, de alguna manera. Si reemplaza printfcon echo, ¿el tiempo mejora significativamente?
obispo
2
Archivo 40G procesado en 2.2282 segundos? ¿Dónde puedo conseguirme esa laptop?
John B
2
@JohnB umm, sí, lo siento, eso fue 40M, no G :)
terdon
Me gusta restablecer el $1enfoque con awk. La cutsolución es definitivamente mucho más rápida, pero eso es de esperarse ya que no se reemplaza <alphanumerical_identifier>con nada. Creo que el más rápido awkvariante podría ser algo como: mawk 'BEGIN{FS=OFS=","}{$1=NR}1' file.csv > newfile.csv.
John B
@ John Ah, sí, supongo que usar en OFSlugar de imprimir explícitamente ,sería un poco más rápido y eso puede sumar una diferencia significativa en un archivo enorme.
terdon