안녕하세요. 인천고래입니다.
데이터베이스를 사용하지 않고 시계열 데이터를 엑셀 파일로 관리하는 경우가 있는데요.
예를 들어 통합적인 관리를 하기 위해 개별적인 종목별 주가 데이터가 저장된 엑셀 파일을 모두 로드해서 하나의 데이터프레임에 저장한 뒤 엑셀 파일로 통합하는 경우가 있습니다.
이 때 각 종목의 데이터가 많은 경우 메모리 부족 (MemoryError) 에러가 발생이 될 수 있습니다.
일반적으로 데이터프레임은 메모리에 상주해 있는 데이터이고 엑셀로 저장을 할 때 추가적인 메모리를 사용하지 않아도 될 것 같은데 실제로는 추가적인 메모리를 필요로 함으로써 메모리가 부족한 현상이 발생되게 됩니다.
좀 더 자세히 말씀을 드리자면
데이터프레임을 엑셀 파일로 변환할 때 추가적인 메모리 사용이 발생하는 이유는 변환 과정에서 생기는 메모리 오버헤드 때문입니다.
여기에는 몇 가지 주요 요인이 있습니다:
1. 데이터 변환 및 서식 지정 데이터프레임을 엑셀 파일로 변환할 때, pandas와 openpyxl 같은 라이브러리는 내부적으로 데이터의 형식을 변경하고, 엑셀 파일에 맞게 서식을 지정합니다. 이 과정에서 원본 데이터프레임 외에 추가적인 메모리가 사용됩니다. 예를 들어, 날짜나 숫자 데이터를 엑셀에서 사용할 수 있는 형식으로 변환하거나, 셀 서식을 설정하는 등의 작업이 포함됩니다.
2. 임시 객체 생성 엑셀 파일로의 변환 과정에서는 원본 데이터 외에도 여러 임시 객체가 메모리에 생성될 수 있습니다. 예를 들어, pandas는 내부적으로 엑셀 파일을 생성하기 위해 데이터를 임시 버퍼에 저장하거나, openpyxl 객체를 생성하여 데이터를 관리할 수 있습니다. 이러한 임시 객체들도 메모리를 추가로 사용합니다.
3. 파일 쓰기 버퍼 실제 파일로 저장하는 과정에서는 파일 쓰기 버퍼가 사용됩니다. 이 버퍼는 디스크에 데이터를 효율적으로 쓰기 위해 메모리에 임시로 데이터를 저장하는 공간입니다. 특히, 대용량 데이터를 처리할 때는 이러한 버퍼링 과정이 메모리 사용량을 증가시킬 수 있습니다.
4. 라이브러리의 메모리 관리 방식 사용하는 라이브러리(pandas, openpyxl 등)의 내부 구현에 따라 메모리 관리 방식이 다를 수 있습니다. 일부 라이브러리는 메모리 효율성을 최적화하기 위해 설계되었지만, 데이터를 파일로 변환하는 과정에서는 필연적으로 추가 메모리가 필요할 수 있습니다.
이러한 이유로, 이미 메모리에 로드되어 있는 데이터프레임을 엑셀 파일로 변환하는 과정에서도 추가적인 메모리 사용이 발생할 수 있으며, 이는 메모리 오버헤드로 인해 MemoryError를 발생시킬 수 있습니다. 대용량 데이터를 처리할 때는 이러한 메모리 사용량을 고려하여 적절한 방법을 선택하는 것이 중요합니다.
그럼 아래와 같이 대용량의 데이터프레임을 엑셀 파일로 만들 때 발생하는 메모리 오류를 해결 방법은 없는 걸까요?
all_signals_df.to_excel(f"data/signal/081_all_signals_data_{today_date_str}.xlsx", index=True)
메모리 에러를 해결할 수 있는 방법은 아래와 같습니다.
if len(all_signals_df) > 0:
file_path = f"data/signal/081_all_signals_data_{today_date_str}.xlsx"
# openpyxl Workbook 생성
wb = Workbook()
ws = wb.active
# 엑셀 파일의 첫 번째 행에 컬럼명 추가
ws.append(list(all_signals_df.columns))
# all_signals_df의 각 행을 엑셀 파일에 추가
for index, row in all_signals_df.iterrows():
ws.append(list(row))
# 엑셀 파일 저장
wb.save(file_path)
print("모든 종목에 대한 Signal 정보를 취합하였습니다.")
위와 같은 방식의 코드는 all_signals_df 데이터프레임의 각 행을 순회하며,
각 행의 데이터를 새로운 엑셀 파일의 행으로 추가합니다. 첫 번째 행에는 데이터프레임의 컬럼명을 추가합니다.
이 방식은 데이터프레임 전체를 한 번에 메모리에 로드하여 엑셀 파일로 저장하는 것이 아니라,
한 행씩 순차적으로 파일에 쓰므로 메모리 사용량을 줄일 수 있습니다.
이렇게 수정한 코드는 pandas의 to_excel() 메서드를 사용하는 것보다 메모리 사용량을 크게 줄이면서 대용량 데이터를 엑셀 파일로 저장할 때 유용합니다.
이번 글을 통해 엑셀로 변환시 메모리 부족 현상을 없애고 우회하여 엑셀로 저장하는 코드에 대해 알아보았습니다.
수고 하셨습니다.
감사합니다.
'Python Code' 카테고리의 다른 글
Python 모듈의 버전을 확인하는 방법 (0) | 2024.05.10 |
---|---|
비동기식 프로그래밍을 위한 async/await, asyncio 사용법 (0) | 2024.04.05 |
32비트 가상환경과 64비트 가상환경 구축 명령어의 차이점에 대하여 (0) | 2024.04.04 |
아나콘다에서 32비트 가상환경 만들기 (0) | 2024.04.04 |
아나콘다에서 64비트 가상환경 만들기 (0) | 2024.04.04 |
댓글