차밍이
[Python] Pandas 대용량 데이터 불러오기 어려울 때, 데이터 형식 변환해 읽기 본문
반응형
목차
Pandas로 대용량 데이터 분석을 진행하다보면 문제가 겪는 어려움 들이 많다.
pandas로 데이터를 읽는데 어려움이 있는 경우 취할 수 있는 방법이다.
1. 파일이 불러와지지 않는 경우
대략적인 과정
column
명 만 먼저 가져온다.- 각 데이터 테이블에서 특정
column
의 데이터만 가져온다. - 해당
column
의 데이터 타입을 확인한다. - 해당
column
의 데이터 범위를 확인하여, 데이터 타입을 줄일 수 있는 경우 타입을 변경해 줄인다. - 전체
column
에 대해서 진행한다. - 이 후
pd.read_csv
를 통해 데이터를 읽어올 때, 데이터 타입을 정해서 읽어오도록 한다.
소스코드 - 파일이 불러와지지 않는 경우
def check_dtypes(file_path:str) -> dict:
print(file_path)
tmp = pd.read_csv(file_path, nrows=0)
col_dtypes = {}
for col in tmp.columns:
df = pd.read_csv(file_path, usecols=[col])
dtype = str(df[col].dtype)
if "int" in dtype or "float" in dtype:
c_min = df[col].min()
c_max = df[col].max()
elif dtype == "object":
n_unique = df[col].nunique()
threshold = n_unique / df.shape[0]
if "int" in dtype:
if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:
col_dtype = "int8"
elif c_min > np.iinfo(np.uint8).min and c_max < np.iinfo(np.uint8).max:
col_dtype = "uint8"
elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:
col_dtype = "int16"
elif c_min > np.iinfo(np.uint16).min and c_max < np.iinfo(np.uint16).max:
col_dtype = "uint16"
elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
col_dtype = "int32"
elif c_min > np.iinfo(np.uint32).min and c_max < np.iinfo(np.uint32).max:
col_dtype = "uint32"
elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:
col_dtype = "int64"
elif c_min > np.iinfo(np.uint64).min and c_max < np.iinfo(np.uint64).max:
col_dtype = "uint64"
else:
col_dtype = "uint64"
elif "float" in dtype:
if c_min > np.iinfo(np.float32).min and c_max < np.iinfo(np.float32).max:
col_dtype = "float32"
else:
col_dtype = "float64"
elif dtype == "object":
if threshold > 0.7:
col_dtype = "object"
else:
col_dtype = "category"
col_dtypes[col] = col_dtype
return col_dtypes
check_dtypes(os.path.join(tar_path, "2a997e23-6334-45c1-a075-8c2f4bfd89d2_015.csv"))
뚱뚱하고 굼뜬 판다스(Pandas)를 위한 효과적인 다이어트 전략 - 오성우 - 에서 나왔던 소스코드를 현재 버전에서 바뀐 부분 일부 수정 + 파일에 대해서 사용할 수 있도록 수정 및 보완했다.
장단점
장점
파일의 크기가 너무 커서 불러올 수 없는 경우, 데이터 테이블 용량을 줄여서 가져올 수 있다.
단점
매우 느리다.
전체 데이터 테이블의 각 컬럼을 다 순회하면서 파일을 가져와 데이터 크기를 확인하는 과정 때문에 매우 느릴 수 밖에 없다.
2. 파일이 불러와 지는 경우
메모리 용량 줄이기
일단 데이터프레임 형태로 데이터를 불러올 수 있다면,
위의 소스코드 함수를 사용하는 것 보다는
불러온 후 메모리 용량 줄이는 것이 더 효과적이다.
소스코드 - 데이터 불러온 후 메모리 용량 줄이기
def reduce_mem_usage(df, verbose=True):
numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']
start_mem = df.memory_usage().sum() / 1024**2
for col in df.columns:
col_type = df[col].dtypes
if col_type in numerics:
c_min = df[col].min()
c_max = df[col].max()
if str(col_type)[:3] == 'int':
if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:
df[col] = df[col].astype(np.int8)
elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:
df[col] = df[col].astype(np.int16)
elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
df[col] = df[col].astype(np.int32)
elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:
df[col] = df[col].astype(np.int64)
else:
if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:
df[col] = df[col].astype(np.float16)
elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:
df[col] = df[col].astype(np.float32)
else:
df[col] = df[col].astype(np.float64)
end_mem = df.memory_usage().sum() / 1024**2
if verbose: print('Mem. usage decreased to {:5.2f} Mb ({:.1f}% reduction)'.format(end_mem, 100 * (start_mem - end_mem) / start_mem))
return df
반응형
'파이썬' 카테고리의 다른 글
코린이에게 추천하는 코딩강의 - 코드잇 - 직접 듣고 느낀 후기 (0) | 2022.07.05 |
---|---|
[Python] Pandas 대용량 데이터 다루기 (0) | 2022.06.03 |
[Python] 파이썬으로 나만의 텔레그램 봇 만들기 (2) | 2021.05.31 |
[Python] 파이썬 자료형 및 연산자의 시간 복잡도(Big-O) 총 정리 (0) | 2020.02.26 |
관련된 글 보기
Comments