본문 바로가기
SQL, Database

데이터프레임 최적화

by yj-data 2025. 8. 19.

목차


    • 메모리를 절약하는 방법
    • 연산을 빠르게 수행하는 방법
    import sys
    import numpy as np
    import pandas as pd
    
    # 데이터 프레임 불러오기
    df = pd.read_csv('orders.csv')
    df.tail(2)
    
    sys.getsizeof(df) / 1024 / 1024, 'mb'  #(97.25404834747314, 'mb')
    
    df.info(memory_usage='deep')

     

    1. 메모리 절약

    • 코드화
      • 문자열 카테고리 > 코드형
    df['eval_set'].unique() #array(['prior', 'train', 'test'], dtype=object)
    mapping_data = {'prior':1, 'train':2, 'test':3}
    df['eval_set'] = df['eval_set'].map(mapping_data) #'eval_set' dtypes : object => int64
    
    df.info(memory_usage='deep') #97.3 > 53.4 MB

     

    • 데이터타입
      • 적절한 데이터타입
    Data Type Size Value Range Memory Usage (10,000 rows)
    bool 1 byte True / False 9.7 KB
    int8 1 byte -128 to 127 9.7 KB
    int16 2 bytes -32768 to 32767 19.5 KB
    int32 4 bytes -2**16 to 2**16 - 1 39.0 KB
    int64 8 bytes -2**32 to 2**32 - 1 78.1 KB
    float32 4 bytes   39.0 KB
    float64 8 bytes   78.1 KB
    complex128 16 bytes   156.3 KB
    datetime64[ns] 8 bytes   78.1 KB
    object variable   656.6 KB
    df['user_id'].dtype  #dtype('int64')
    np.min(df['user_id']),np.max(df['user_id'])  #(1, 60078)
    
    dtype = np.uint16  #uint => unsigned int
    np.iinfo(dtype).min, np.iinfo(dtype).max  #(0, 65535)
    
    
    #회사에서는 코드를 만들어서 df넣으면 적절하게 변경되어서 데이터타입이 바뀐 채로 튀어나오게 만들어둠
    df['user_id'] = df['user_id'].astype(np.uint16) #int64에서 uint16 으로 변경
    
    df.info(memory_usage='deep') # 53.4 > 47.7 MB
    • 데이터 타입
      • 문자열 데이터 : Object > Category
    #category는 몇가지 종류의 문자열을 넣어준다 라는 뜻. 문자열 데이터로 남기되(숫자형으로 변경x) 크기 줄이기
    df = pd.read_csv('orders.csv')
    df.tail(1)
    
    df['eval_set'] = df['eval_set'].astype('category')
    df.dtypes
    
    df.info(memory_usage='deep')  #97.3 > 46.7 MB


    2. 벡터화: 데이터 하나씩 연산하는것보다 벡터로 한꺼번에 연산하는것이 빠름

    예,
    [1] + [3]
    [2] + [4]
    보다
    
    [1, 2] + [3, 4]
    가 빠름
    rows = int(1E4) # 10000개 (1과 공 네개)
    data = {
        'id': np.arange(rows),
        'category': np.random.choice(list('ABCD'),rows),  #['a'...] 보다 list('abcd') 이렇게 씀
        'value': np.random.rand(rows)*100,  #random.rand 는 균등분포가 생성됨
        'count' : np.random.randint(1,100,rows), #1부터 99까지 수 랜덤
    }
    df = pd.DataFrame(data)
    df.tail(2)
    df.dtypes
    
    #value * count 연산
    df1 = df.copy()
    df1['mul'] = .0  #float형으로 열 만들기
    df1.tail(1)
    
    %%time
    #1: 반복문 사용 -> 하나씩 연산해서 데이터 채움
    for idx, row in df1.iterrows():
        df1.loc[idx,'mul'] = row['value'] * row['count']  #CPU times: total: 1.97 s, Wall time: 2.03 s
        
    %%time
    #2: 반복문 사용 -> 하나씩 연산해서 리스트를 만들고 한번에 채움
    mul_list=[]
    for idx, row in df1.iterrows():
        mul_list.append(row['value'] * row['count'])
    df1['mul'] = mul_list  #CPU times: total: 484 ms, Wall time: 473 ms
    
    %%time
    #3: 벡터로 연산해서 한번에 채움
    df1['mul'] = df1['value'] * df1['count']  #CPU times: total: 0 ns, Wall time: 999 μs