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.

Cómo obtener un dataframe de pandas por fragmentos desde archivos csv en un archivo tar.gz enorme sin descomprimir y sin iterar sobre ellos?

Tengo un archivo comprimido enorme en el que estoy interesado en leer los dataframes individuales, para no quedarme sin memoria.

Además, debido al tiempo y al espacio, no puedo descomprimir el archivo .tar.gz.

Este es el código que tengo hasta ahora:

import pandas as pd
# Con esta biblioteca podemos navegar por archivos comprimidos
# sin siquiera extraer su contenido
import tarfile
import io

tar_file = tarfile.open(r'\ruta\al\archivo\tar\file.tar.gz')

# Con el siguiente código podemos iterar sobre los archivos CSV contenidos en el archivo comprimido
def generate_individual_df(tar_file):
    return \
        (
            (
                member.name, \
                pd.read_csv(io.StringIO(tar_file.extractfile(member).read().decode('ascii')), header=None)
            )
               for member in tar_file
                   if member.isreg()\
        )

for filename, dataframe in generate_individual_df(tar_file):
    # Pero el dataframe es el archivo completo, que es demasiado grande

Intenté el enlace https://stackoverflow.com/questions/39191111/how-to-create-panda-dataframe-from-csv-that-is-compressed-in-tar-gz, pero aún no puedo resolverlo…

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para evitar quedarse sin memoria y omitir la descompresión del archivo comprimido .tar.gz, puedes utilizar el método read_csv() de pandas para leer una porción específica del archivo como un dataframe. Un enfoque podría ser leer primero la cabecera del archivo para determinar los nombres de las columnas, y luego iterar sobre el archivo usando read_csv() con el parámetro skiprows para leer lotes de dataframes. A continuación se muestra un código de ejemplo que demuestra este enfoque:

    import pandas as pd
    import tarfile
    import io
    
    tar_file = tarfile.open(r'ruta/al/archivo.tar.gz')
    
    # Leer la cabecera para obtener los nombres de las columnas
    header_buf = io.StringIO(tar_file.extractfile('nombrearchivo.csv').readline().decode('utf-8'))
    header = pd.read_csv(header_buf, header=None).iloc[0].tolist()
    
    # Leer el archivo en lotes
    tamaño_lote = 100000
    for i, lote in enumerate(pd.read_csv(io.StringIO(tar_file.extractfile('nombrearchivo.csv').read().decode('utf-8')),
                                   header=None, skiprows=1, chunksize=tamaño_lote)):
        # Renombrar las columnas
        lote.columns = header
    
        # Hacer algo con el lote
        print(lote)
    

    En este ejemplo, primero abrimos el archivo comprimido usando tarfile, y luego leemos la cabecera de uno de los archivos CSV internos para obtener los nombres de las columnas. Luego usamos pd.read_csv() con el parámetro skiprows para leer el archivo en lotes de 100,000 filas, y renombramos las columnas para que coincidan con la cabecera. Puedes ajustar el tamaño del lote a un valor que se ajuste a las limitaciones de memoria.

Comments are closed.