본문 바로가기
Programming/Python

[Python] 압축 파일(zip) 다루기 (ft. 압축 풀지 않고 데이터 읽기)

by a voyager 2021. 6. 14.
728x90
반응형

St. John's Cathederal in Hong Kong Central 

목차

     

    많은 양의 데이터를 이동하거나 보관할 때 주로 이들을 압축하며, zip과 tar 확장자가 대표적이다. 최근 시그널 프로세싱에 관련된 데이터 분석을 하면서 많은 실험 데이터를 다루게 되었다. 이것들은 실험의 조건에 따라 여러 그룹으로 나누어져 있고, 각 조건마다 수십 개의 파일들이 있어 데이터를 옮기는 데만 상당히 많은 시간이 걸리게 되었다. 클라우딩 스토리지를 사용하면 좋겠지만, 아직 그 단계의 시스템이 구축된 것이 아니어서 일단 압축 파일의 형태로 데이터를 옮기고 읽어 들이기로 하였다. 

     

    이번 포스팅에서 python에서 zip 파일의 압축을 풀고 데이터를 읽는 법에 대해서 정리해보았다. 또한, 압축을 풀지 않고 내부 파일의 데이터를 로딩하는 방법에 대해서도 정리했다. 특히, 후자의 경우는 디스크 사용량을 줄이거나 데이터 관리를 하는데 있어 유용할 것으로 생각된다. 

     

    우선 필요한 모듈들을 import한다. 이중 zip 파일을 다루는 파이썬 모듈은 ZipFile이다. 

    import os 
    import io
    import zipfile
    from zipfile import ZipFile
    import pandas as pd
    import requests
    import tensorflow as tf

     

    포스팅의 과정을 따라갈 수 있게 하기 위해 실제로 다섯개의 파일이 압축되어 있는  VSB Power Line Fault Detection dataset 를 이용해보자. 이 링크로부터 zip 파일로 압축되어 있는 데이터를 다운로드할 수 있다. 아래와 같이 'vsb-power-line-fault-detection.zip' 이 생긴 것을 확인한다. 

    !ls

     

    현재 디렉토리에 있는 zip 파일을 출력해본다. 

    zipfiles = [ file for file in os.listdir() if file.endswith('zip')]
    print(zipfiles)

     

    압축 풀기 

    압축된 파일 리스트 확인하기 

    압축을 풀기전 zip 파일에 어떤 파일들이 묶여 있는지 확인할 수 있다. zipfile의 namelist()라는 메서드를 이용한다. 이 과정은 압축을 푸는 것이 아니라, 단지 zip 파일에 어떤 파일들이 있는지 확인하는 것이다. 

    with ZipFile('vsb-power-line-fault-detection.zip', 'r') as zipObj:
        listOfFileNames = zipObj.namelist()
        for fileName in listOfFileNames:
            print(fileName)

    세 개의 csv파일과 두 개의 parquet파일 

     

    압축을 풀 디렉토리를 만들고 압축 풀기 

    zipFile의 extractall()이라는 메서드를 이용해 압축을 풀 수 있고, input argument로 압축을 풀 디렉토리 이름을 줄 수 있다. 그러면 압축 해제된 파일들이 지정된 디렉토리에 위치하게 된다. 다음과 같이 실행하여 vsb-power-line-fault-detection.zip 파일을 vsb-power-line-fault-detection이라는 디렉토리에 압축을 풀어준다. 

    with ZipFile('vsb-power-line-fault-detection.zip', 'r') as zipObj:
        zipObj.extractall('vsb-power-line-fault-detection')
        
        
    !ls

     

    ls로 디렉토리가 만들어진 것을 확인하고, 이 디렉토리 안의 압축이 풀린 파일들을 확인한다. 

    # 압축이 풀린 5개의 파일이 생긴것을 볼 수 있다. 
    os.listdir('vsb-power-line-fault-detection/')

     

    원하는 특정 파일만 축출하기 

    위와 같이 extractall()을 이용하면 모든 파일의 압축을 풀 수 있다. 반면, 원하는 파일만 골라서 축출할 수 있는 방법이 있다.

     

    예를 들어 위의 다섯개의 파일 중 csv파일만 필요하다고 해보자. 다음과 같이 파일명을 확인하고 그중에 csv를 확장자로 가지는 파일만 extract()하는 것이다. 이때도 역시 축출한 파일을 놓을 디렉토리를 만들 수 있다. CSV_files라고 해보자. 

    with ZipFile('vsb-power-line-fault-detection.zip', 'r') as zipObj:
        listOfFileNames = zipObj.namelist()
        for fileName in listOfFileNames:
            if fileName.endswith("csv"):
                zipObj.extract(fileName, 'CSV_files')

     

    ls로 CSV_files 디렉토리가 만들어진 것을 확인한다. 

    !ls

     

    os.listdir로 CSV_files 디렉토리의 파일을 확인한다. 의도한 대로 CSV 포맷의 파일 세 개만 압축이 풀여 있다. 

    os.listdir("CSV_files")

     

    압축을 풀지 않고 데이터 로딩하기 

    지금까지 python의 zipFile의 extractall()과 extract() 메소드를 이용해 압축 파일을 추출하는 법을 알아보았다. 이번에는 압축을 풀지 않고 zip 파일 내의 파일들을 읽어 데이터로 로딩하는 방법에 대해서 알아보도록 하자. 이렇게 한다면, 분석하기 위한 데이터를 항상 압축된 형태로 보관할 수 있어 디스크 사용량 관리와 더불어 많은 종류의 데이터를 관리하는 데도 큰 도움이 된다. 

     

    단일 압축 파일 읽기 

    우선 하나의 csv파일이 zip으로 압축된 경우를 다뤄보자. 예제 파일로 jena climate이라는 데이터셋을 골랐고, 아래의 링크에서 csv.zip파일을 내려받을 수 있다. 

    url = 'https://storage.googleapis.com/tensorflow/tf-keras-datasets/jena_climate_2009_2016.csv.zip'

     

    • url로부터 압축 파일 내려받기 : request 모듈

    requests 모듈을 이용해 아래와 같이 파일을 다운로드할 수 있다. 

    def download(url):
        get_response = requests.get(url)
        file_name  = url.split("/")[-1]
        with open(file_name, 'wb') as f:
            for chunk in get_response.iter_content(chunk_size=1024):
                if chunk: # filter out keep-alive new chunks
                    f.write(chunk)
        print("file name to be downloaded: {}".format(file_name))
        print("is downloaded? {}".format(os.path.exists(file_name)))
    
    download(url)
    

    !ls

    jena_climate csv.zip 파일이 생겼다

     

    pandas.read_csv는 zip파일로 된 csv파일도 읽는다. 아래와 같이 데이터를 확인한다. 

    pd.read_csv('jena_climate_2009_2016.csv.zip')

     

    • url로부터 압축 파일 내려받기 : tensorflow 이용

    이번에는 tensorflow를 이용해 url 데이터를 받을 수 있다. 

    zip_path = tf.keras.utils.get_file(
        origin='https://storage.googleapis.com/tensorflow/tf-keras-datasets/jena_climate_2009_2016.csv.zip',
        fname='jena_climate_2009_2016.csv.zip',
        extract=False)
    zip_path

    pd.read_csv(zip_path)

    requests로 읽은 것과 동일한 데이터셋

     

     

    압축된 여러 파일을 읽기 

    이번에는 여러 csv파일이 압축된 zip 파일로부터 각각의 csv 데이터를 압축을 풀지 않은 채로 로딩해보자. 'vsb-power-line-fault-detection.zip'에서 세 개의 csv파일을 압축 해제 없이 읽어 들인다. 

    from io import BytesIO
    
    data_filename = []
    data=[] 
    with ZipFile('vsb-power-line-fault-detection.zip', 'r') as zipObj:
        listOfFileNames = zipObj.namelist()
        for fileName in listOfFileNames:
            if fileName.endswith('csv'): 
                print(fileName)
                zipRead = zipObj.read(fileName)
                curr_df = pd.read_csv(BytesIO(zipRead))
                data.append(curr_df)
                data_filename.append(fileName)

     

    data라는 리스트에 저장했다. 이 리스트에 세 개의 dataframe이 더해진 것을 확인한다. 

    print("the number of loaded csv files : {}".format(len(data)))

     

    각각의 데이터를 출력하여, 데이터가 잘 읽어 들여졌는지 확인한다. 

    for filename, d in zip(data_filename, data): 
        print("--------------------------")
        print(filename)
        display(d.head(5))

     

    참고한 링크 

     

     

     

    728x90
    반응형

    댓글