es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Dividir archivo CSV grande en varios archivos basados en columnas(s).

Me gustaría saber una forma rápida y eficiente en cualquier programa (awk/perl/python) para dividir un archivo csv (digamos de 10k columnas) en varios archivos pequeños, cada uno conteniendo 2 columnas. Estaría haciendo esto en una máquina unix.


<h1>contenido de large_file.csv</h1> 1,2,3,4,5,6,7,8 a,b,c,d,e,f,g,h q,w,e,r,t,y,u,i a,s,d,f,g,h,j,k z,x,c,v,b,n,m,z

Ahora quiero varios archivos como este:


<h1>contenido de 1.csv</h1> 1,2 a,b q,w a,s z,x <h1>contenido de 2.csv</h1> 1,3 a,c q,e a,d z,c <h1>contenido de 3.csv</h1> 1,4 a,d q,r a,f z,v

y así sucesivamente…

Actualmente puedo hacer esto con awk en archivos pequeños (digamos de 30 columnas) de esta manera:

awk -F, 'BEGIN{OFS=",";} {for (i=1; i < NF; i++) print $1, $(i+1) > i ".csv"}' large_file.csv

Lo anterior tarda mucho tiempo con archivos grandes y me preguntaba si hay una forma más rápida y eficiente de hacer lo mismo.

Gracias de antemano.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Como experto en TI especializado en perl, awk y manipulación de datos, puedo sugerir algunas opciones para dividir un archivo CSV grande en archivos más pequeños que contengan solo 2 columnas cada uno.

    Opción 1: Usando Perl

    Un enfoque utilizando Perl sería leer el archivo CSV más grande y luego iterar sobre cada fila, creando una nueva fila que contenga solo las dos primeras columnas. Esto se puede escribir en un nuevo archivo, que contendrá solo las 2 columnas deseadas. El código se vería así:

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    # Abrir el archivo CSV de entrada
    open my $csv_in, '<', 'large_file.csv' or die "No se puede abrir el archivo de entrada: $!";
    
    # Inicializar un contador
    my $counter = 1;
    
    # Inicializar el archivo de salida para el primer archivo
    my $out_fh = open_output_file($counter);
    
    # Iterar sobre cada fila del archivo de entrada
    while (my $line = <$csv_in>) {
      # Dividir la línea en un arreglo basado en las comas
      my @fields = split /,/, $line;
    
      # Escribir solo los primeros dos campos en el archivo de salida
      print $out_fh "$fields[0],$fields[1]\n";
    
      # Si el archivo actual alcanza dos columnas, incrementar el contador y abrir un nuevo archivo de salida
      if (($.%2) == 0) {
        $counter++;
        $out_fh = open_output_file($counter);
      }
    }
    
    # Cerrar el archivo de entrada
    close $csv_in;
    
    # Cerrar el último archivo de salida
    close $out_fh;
    
    # Función para abrir un nuevo archivo de salida
    sub open_output_file {
      my $count = shift;
    
      my $filename = $count . '.csv';
    
      open my $fh, '>', $filename or die "No se puede crear el archivo de salida: $!";
    
      return $fh;
    }
    

    Opción 2: Usando AWK

    Un enfoque similar usando AWK sería iterar sobre cada fila del archivo de entrada y luego imprimir solo las primeras dos columnas en un archivo de salida determinado por un contador. El código se vería así:

    #!/usr/bin/awk -f
    
    BEGIN {
        FS=",";
        OFS=",";
        counter = 1;
        output_file = counter".csv";
    }
    {
        # Solo imprimir las primeras dos columnas
        print $1,$2 > output_file;
    
        # Si el archivo actual alcanza dos columnas, incrementar el contador y abrir un nuevo archivo de salida
        if((NR%2) == 0) {
            close(output_file);
            counter++;
            output_file = counter".csv";
        }
    }
    

    Opción 3: Usando Python

    Una tercera opción utilizando Python sería iterar sobre cada fila del archivo de entrada y usar el módulo CSV para escribir solo las primeras dos columnas en un archivo de salida determinado por un contador. El código se vería así:

    #!/usr/bin/env python
    
    import csv
    
    # Abrir el archivo CSV de entrada
    with open('large_file.csv', 'r') as csv_in:
        reader = csv.reader(csv_in)
        counter = 1
        output_file = open_output_file(counter)
    
        # Iterar sobre cada fila del archivo de entrada
        for row in reader:
            # Escribir solo las primeras dos columnas en el archivo de salida
            output_file.write(','.join(row[:2]))
    
            # Si el archivo actual alcanza dos columnas, incrementar el contador y abrir un nuevo archivo de salida
            if (reader.line_num % 2) == 0:
                counter += 1
                output_file.close()
                output_file = open_output_file(counter)
    
        # Cerrar el archivo de entrada y el último archivo de salida
        csv_in.close()
        output_file.close()
    
    # Función para abrir un nuevo archivo de salida
    def open_output_file(counter):
        filename = str(counter) + '.csv'
        return open(filename, 'w')
    

    Las tres opciones deberían ser más eficientes que la solución AWK que está utilizando actualmente. Sin embargo, puede ser necesario realizar pruebas para determinar qué solución es la más eficiente en su sistema particular con un archivo del tamaño con el que está trabajando.

Comments are closed.