팬더로 분석하기 위해 20GB 파일 열기


33

현재 머신 러닝 목적으로 팬더와 파이썬으로 파일을 열려고합니다. 데이터 프레임에 모두 넣는 것이 이상적입니다. 이제 파일 크기는 18GB이고 RAM은 32GB이지만 메모리 오류가 계속 발생합니다.

당신의 경험에서 가능합니까? 이 문제를 해결하는 더 좋은 방법을 모르십니까? (하이브 테이블? RAM의 크기를 64로 늘리십시오. 데이터베이스를 만들고 파이썬에서 액세스하십시오)


동일한 문제가 발생했습니다. 하드 드라이브의 스왑, 페이징 및 크기를 늘리는 것이 좋습니다.
Media

데이터를로드 할 때 일반적으로 pandas5 ~ 10 배 더 많은 RAM이 필요합니다. inplace작업을 수행하고 garbage.collector개체 할당을 명시 적으로 호출 하는 것이 좋습니다 .
Kiritee Gak

4
최종 목표를 명시하여이 질문을 더 잘하십시오. 탐색 적 데이터 분석, 데이터 정리, 모델 교육 또는 무엇을하고 있습니까? 어떤 종류의 데이터?
Pete

1
dask 사용을 고려 했습니까 ?
rpanai

답변:


32

csv 파일이고 알고리즘을 학습 할 때 한 번에 모든 데이터에 액세스 할 필요가없는 경우 청크로 읽을 수 있습니다. 이 pandas.read_csv방법을 사용하면 다음과 같이 덩어리로 파일을 읽을 수 있습니다.

import pandas as pd
for chunk in pd.read_csv(<filepath>, chunksize=<your_chunksize_here>)
    do_processing()
    train_algorithm()

메소드의 문서 는 다음과 같습니다


이것은 zip 파일에도 적용됩니까?
James Wierzba

압축 파일이 csv 파일 인 경우에도 작동해야합니다. 압축 유형을 메소드의 인수로 전달해야합니다.
Olel Daniel

22

이 두 가지 가능성이 있습니다 : 하나 당신이 필요합니다 (예를 들어, 귀하의 기계 학습 알고리즘은 한 번에 그것 모두를 소비 할 것) 처리를 위해 메모리에 모든 데이터를 가지고, 또는 당신이없이 할 수 있습니다 (예를 들어, 알고리즘은 행의 샘플이 필요하거나 한 번에 열).

첫 번째 경우 에는 메모리 문제해결 해야합니다 . 메모리 크기를 늘리고, 고용량 클라우드 머신을 대여하고, 내부 작업을 사용하고, 읽고있는 데이터 유형에 대한 정보를 제공하고, 사용하지 않는 모든 변수를 삭제하고 가비지를 수집하십시오.

32GB의 RAM으로는 팬더가 데이터를 처리하기에 충분하지 않을 가능성이 큽니다. 정수 "1"은 텍스트로 저장 될 때 1 바이트이지만 다음과 같이 표현 될 때 8 바이트입니다 int64(Pandas가 텍스트에서 읽을 때 기본값 임). 부동 소수점 숫자 "1.0"을 사용하여 동일한 예를 만들 수 있으며 float64기본적으로 3 바이트 문자열에서 8 바이트로 확장됩니다 . Pandas에게 각 열에 사용할 유형을 정확하게 알려주고 가능한 가장 작은 표현을 강요하여 공간을 확보 할 수는 있지만 여기에서 파이썬 포인터의 데이터 구조 오버 헤드에 대해 말하기 시작하지 않았습니다. 포인터는 64 비트 시스템에서 각각 8 바이트입니다.

요약하자면, 아니요, 32GB RAM은 팬더가 20GB 파일을 처리하기에 충분하지 않을 수 있습니다.

두 번째 경우 (보다 현실적이고 아마도 적용 할 수 있음) 데이터 관리 문제 를 해결해야합니다 . 실제로 처리를 위해 데이터의 일부만 필요할 때 모든 데이터를로드해야하는 경우 데이터 관리가 잘못 될 수 있습니다. 여기에 여러 옵션이 있습니다 :

  1. SQL 데이터베이스를 사용하십시오. 가능하다면 거의 항상 첫 번째 선택이며 괜찮은 솔루션입니다. 20GB의 사운드는 대부분의 SQL 데이터베이스가 (최고급) 랩톱에서도 배포 할 필요없이 잘 처리 할 수있는 크기입니다. 간단한을 사용하여보다 복잡한 처리를 위해 열을 색인화하고 SQL을 통해 기본 집계를 수행하고 필요한 서브 샘플을 Pandas로 가져올 수 pd.read_sql있습니다. 데이터를 데이터베이스로 이동하면 열의 실제 데이터 유형 및 크기에 대해 생각할 수 있습니다.

  2. 데이터가 대부분 숫자 (예 : 배열 또는 텐서) 인 경우 데이터를 HDF5 형식 ( PyTables 참조 ) 으로 유지하면 디스크에서 필요한 거대한 배열의 슬라이스 만 편리하게 읽을 수 있습니다. 기본 numpy.save 및 numpy.load 는 디스크에서 어레이를 메모리 매핑하여 동일한 효과를 얻습니다. GIS 및 관련 래스터 데이터에는 전용 데이터베이스있습니다.이 데이터베이스 는 SQL만큼 직접 팬더에 연결할 수 없지만 슬라이스와 쿼리를 합리적으로 편리하게 수행 할 수 있어야합니다.

  3. 팬더는 내가 아는 한 HDF5 또는 numpy 배열의 "부분"메모리 매핑을 지원하지 않습니다. 여전히 "순수한 판다"솔루션을 원한다면, "샤딩 (sharding)"을 통해 문제를 해결할 수 있습니다. 거대한 테이블 의 을 개별적으로 저장 (예 : 별도의 파일 또는 단일 HDF5의 별도의 "테이블") 필요에 따라 필요한 항목 만로드하거나 행 덩어리를 별도로 저장합니다 . 그러나 필요한 청크를로드하기위한 로직을 구현해야하므로 대부분의 SQL 데이터베이스에 이미 구현 된 자전거를 재창조해야하므로 옵션 1이 여전히 더 쉬울 것입니다. 데이터가 CSV로 제공되는 경우 chunksize매개 변수를 로 지정하여 데이터를 청크로 처리 할 수 ​​있습니다 pd.read_csv.


5
"첫 번째 사례"에서 언급해야 할 것은 OP에 데이터에서 값이 같은 항목이 많으면 (예 : 0) 데이터가 희박하다고 말하고 scipy sparse matrix를 사용할 수 있다는 것입니다. 팬더 데이터 프레임-스파 스 데이터에는 훨씬 적은 메모리가 필요합니다.
Ricardo Cruz

9

방금 며칠 전에이 문제가 발생했습니다! 많은 세부 정보를 제공하지 않았기 때문에 이것이 특정 경우에 도움이되는지 확실하지 않지만 제 상황은 '큰'데이터 집합에서 오프라인으로 작업하는 것이 었습니다. 데이터는 몇 초 간격으로 에너지 미터, 시계열 데이터에서 20GB gzipped CSV 파일로 확보되었습니다.

파일 IO :

data_root = r"/media/usr/USB STICK"
fname = r"meters001-050-timestamps.csv.gz"
this_file = os.path.join(data_root,fname)
assert os.path.exists(this_file), this_file
this_file

gzip 파일 바로 위에 청크 반복자를 작성하십시오 (압축 해제하지 마십시오!)

cols_to_keep = [0,1,2,3,7]
column_names = ['METERID','TSTAMP','ENERGY','POWER_ALL','ENERGY_OUT',]
parse_dates = ['TSTAMP']
dtype={'METERID': np.int32, 
       'ENERGY': np.int32,
       'POWER_ALL': np.int32,
       'ENERGY_OUT': np.int32,
      }
df_iterator = pd.read_csv(this_file, 
                        skiprows=0, 
                        compression='gzip',
                        chunksize=1000000, 
                        usecols=cols_to_keep,
                        delimiter=";",
                        header=None,
                        names = column_names,
                      dtype=dtype,
                     parse_dates=parse_dates,
                     index_col=1,
                     )

청크를 반복

new_df = pd.DataFrame()
count = 0
for df in df_iterator:
    chunk_df_15min = df.resample('15T').first()
    #chunk_df_30min = df.resample('30T').first()
    #chunk_df_hourly = df.resample('H').first()
    this_df = chunk_df_15min
    this_df = this_df.pipe(lambda x: x[x.METERID == 1])
    #print("chunk",i)
    new_df = pd.concat([new_df,chunk_df_15min])
    print("chunk",count, len(chunk_df_15min), 'rows added')
    #print("chunk",i, len(temp_df),'rows added')
    #break
    count += 1

청크 루프 내에서 제 시간에 필터링 및 리샘플링을하고 있습니다. 이를 통해 오프라인 데이터를 더 탐색하기 위해 크기를 20GB에서 수백 MB HDF5로 줄였습니다.


5

내 경험상 read_csv()매개 변수 low_memory=False를 사용하여 초기화 하면 큰 파일을 읽을 때 도움이되는 경향이 있습니다. 나는 당신이 읽고있는 파일 형식을 언급하지 않았다고 생각하기 때문에 이것이 당신의 상황에 어떻게 적용되는지 확실하지 않습니다.


1

파일이 CSV 인 경우 Chunk by Chunk에서 간단히 수행 할 수 있습니다. 당신은 단순히 할 수 있습니다 :

import pandas as pd
for chunk in pd.read_csv(FileName, chunksize=ChunkSizeHere)
(Do your processing and training here)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.