아미(아름다운미소)

fillna 최종 본문

랭귀지/pandas

fillna 최종

유키공 2025. 3. 25. 19:04
data = {'a': ['hello', np.nan, 'nan', None]}  # 'nan'은 문자열
df = pd.DataFrame(data)
array = np.where(pd.isna(df['a'].to_numpy()), '', df['a'].to_numpy())
# 결과: ['hello', '', 'nan', '']
import pandas as pd
import numpy as np

# 샘플 데이터 생성
data = {'a': [1, np.nan, 3, np.nan, 5], 'b': [np.nan, 2, np.nan, 4, np.nan]}
df = pd.DataFrame(data)

# 성능 개선된 처리
array = df['a'].to_numpy()  # dtype=object 제거 (float64로 자동 변환)
array = np.where(np.isnan(array), '', array)  # np.isnan 사용
df['a'] = array

print(df)

 

 

import pandas as pd
import numpy as np
import time

# 데이터 생성 (300만 행, 문자열 + 30% NaN)
np.random.seed(42)
data_size = 3_000_000
categories = ['A', 'B', 'C', 'D', 'E', 'F', np.nan]  # NaN 포함
data = np.random.choice(categories, size=data_size, p=[0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.1])  # 10% NaN
df = pd.DataFrame({'text': data})

# 1. fillna() 방식
df_fillna = df.copy()
start = time.time()
df_fillna['text'] = df_fillna['text'].fillna('')  # fillna()로 빈 문자열 대체
fillna_time = time.time() - start

# 2. NumPy 방식
df_numpy = df.copy()
start = time.time()
col = df_numpy['text'].to_numpy()  # NumPy 배열 변환
col[pd.isna(col)] = ''             # pd.isna()로 문자열 NaN 체크
df_numpy['text'] = col
numpy_time = time.time() - start

# 결과 검증
assert df_fillna.equals(df_numpy), "결과 불일치!"

print(f"fillna() 시간: {fillna_time:.5f}초")
print(f"NumPy 시간: {numpy_time:.5f}초")
print(f"NumPy가 {fillna_time / numpy_time:.2f}배 더 빠릅니다.")

 

 

import pandas as pd
import numpy as np
import time
from string import ascii_uppercase

# --------------------------------------------
# 1. 300만 행 × 30컬럼 데이터 생성 (NaN 20% 포함)
# --------------------------------------------
np.random.seed(42)
data_size = 3_000_000  # 300만 행
num_cols = 30          # 30개 컬럼

# 컬럼 이름 생성 (A, B, ..., Z, AA, AB, AC)
column_names = [ascii_uppercase[i] if i < 26 else ascii_uppercase[0] + ascii_uppercase[i-26] 
                for i in range(num_cols)]

data = {}
for col in column_names:
    # 타겟 문자열 컬럼 (G 컬럼으로 지정)
    if col == 'G':
        data[col] = np.random.choice(['Apple', 'Banana', 'Cherry', np.nan], 
                                    size=data_size, p=[0.3, 0.3, 0.3, 0.1])
    # 다른 컬럼들 (숫자 + 문자열 혼합)
    else:
        if np.random.rand() > 0.5:  # 50% 확률로 숫자 컬럼
            data[col] = np.random.rand(data_size) * 100
            data[col][np.random.choice(data_size, int(data_size*0.2))] = np.nan  # 20% NaN
        else:  # 문자열 컬럼
            data[col] = np.random.choice(['X', 'Y', 'Z', np.nan], 
                                        size=data_size, p=[0.3, 0.3, 0.3, 0.1])

df = pd.DataFrame(data)
target_col = 'G'  # 타겟 컬럼 지정

# --------------------------------------------
# 2. 성능 비교 함수 (단일 컬럼 처리)
# --------------------------------------------
def compare_methods(df, target_col):
    # 복사본 생성 (깊은 복사로 독립성 보장)
    df_fillna = df.copy(deep=True)
    df_numpy = df.copy(deep=True)
    
    # (1) fillna() 방식
    start_time = time.time()
    df_fillna[target_col] = df_fillna[target_col].fillna('')
    fillna_time = time.time() - start_time
    
    # (2) NumPy 변환 방식
    start_time = time.time()
    col = df_numpy[target_col].to_numpy()
    col[pd.isna(col)] = ''
    df_numpy[target_col] = col
    numpy_time = time.time() - start_time
    
    # 결과 검증
    assert df_fillna[target_col].equals(df_numpy[target_col]), "결과 불일치!"
    
    return fillna_time, numpy_time

# --------------------------------------------
# 3. 테스트 실행 및 결과 출력
# --------------------------------------------
fillna_time, numpy_time = compare_methods(df, target_col)

print(f"🔍 타겟 컬럼 '{target_col}' 성능 비교 (300만 행)")
print(f"  - fillna() 소요시간: {fillna_time:.5f}초")
print(f"  - NumPy 변환 소요시간: {numpy_time:.5f}초")
print(f"  → NumPy가 {fillna_time / numpy_time:.2f}배 더 빠름")
print(f"  → 절약 시간: {fillna_time - numpy_time:.5f}초")

# --------------------------------------------
# 4. 메모리 및 데이터 타입 확인
# --------------------------------------------
print("\n💽 메모리 정보:")
print(f"  전체 데이터프레임 크기: {df.memory_usage(deep=True).sum() / (1024**2):.2f} MB")
print(f"  '{target_col}' 컬럼 타입: {df[target_col].dtype}")

 

 

 

col = df[target_col].to_numpy()
col[pd.isna(col)] = ''
df[target_col] = col
import pandas as pd
import numpy as np
import time

# --------------------------------------------
# 1. 300만 행의 테스트 데이터 생성 (NaN 30% 포함)
# --------------------------------------------
np.random.seed(42)  # 재현성 보장
data_size = 3_000_000  # 300만 행

# 문자열 + NaN이 섞인 컬럼 (예: 'category')
data = {
    'category': np.random.choice(['A', 'B', 'C', 'D', np.nan], size=data_size, p=[0.25, 0.25, 0.2, 0.1, 0.2]),
    'value': np.random.rand(data_size) * 100  # 숫자 컬럼 (예: 'value')
}

# 숫자 컬럼에 NaN 30% 추가
data['value'][np.random.choice(data_size, size=int(data_size * 0.3), replace=False)] = np.nan

df = pd.DataFrame(data)
target_col_str = 'category'  # 문자열 컬럼
target_col_num = 'value'     # 숫자 컬럼

# --------------------------------------------
# 2. 성능 비교 함수 정의
# --------------------------------------------
def test_fillna_vs_numpy(df, target_col, fill_value):
    # 복사본 생성
    df_fillna = df.copy()
    df_numpy = df.copy()
    
    # (1) fillna() 방식
    start_time = time.time()
    df_fillna[target_col] = df_fillna[target_col].fillna(fill_value)
    fillna_time = time.time() - start_time
    
    # (2) NumPy 변환 방식
    start_time = time.time()
    col = df_numpy[target_col].to_numpy()
    col[pd.isna(col)] = fill_value
    df_numpy[target_col] = col
    numpy_time = time.time() - start_time
    
    # 결과 검증 (두 방법이 동일한지 확인)
    assert df_fillna.equals(df_numpy), "결과가 일치하지 않습니다!"
    
    return fillna_time, numpy_time

# --------------------------------------------
# 3. 테스트 실행 (문자열 vs 숫자 컬럼)
# --------------------------------------------
print("[ 문자열 컬럼 (category) 테스트 ]")
fillna_str, numpy_str = test_fillna_vs_numpy(df, target_col_str, '')
print(f"  fillna() 소요시간: {fillna_str:.5f}초")
print(f"  NumPy 변환 소요시간: {numpy_str:.5f}초")
print(f"  → NumPy가 {fillna_str / numpy_str:.2f}배 더 빠름\n")

print("[ 숫자 컬럼 (value) 테스트 ]")
fillna_num, numpy_num = test_fillna_vs_numpy(df, target_col_num, 0)
print(f"  fillna() 소요시간: {fillna_num:.5f}초")
print(f"  NumPy 변환 소요시간: {numpy_num:.5f}초")
print(f"  → NumPy가 {fillna_num / numpy_num:.2f}배 더 빠름")
Comments