본문 바로가기
STUDY

[멋쟁이사자처럼부트캠프_그로스마케팅] Day 13-1 이상치, 데이터 변환(결측치, 데이터 타입 변환)

by vol2 2025. 2. 26.
     

     

    데이터 변환 및 이상치 처리


    1️⃣ 이상치 (Outlier)

    이상치는 사분위 범위(IQR, Interquartile Range)를 벗어난 값으로 정의됩니다.

    데이터 분석 및 모델링의 신뢰성을 저해하므로 적절한 처리가 필요합니다.


    1.1 이상치(Outlier)의 정의

    • 이상치는 다음 범위를 벗어나는 데이터 포인트를 의미합니다.
    • IQR (Interquartile Range) 정의:

    $$ \text{IQR} = Q3 - Q1 $$

    • 하한 경계값 (Lower Bound)
      • 이상치 판단기준(최솟값)
      Q1−1.5×IQRQ1 - 1.5 \times \text{IQR}
    • $Q1 - 1.5 \times \text{IQR}$
    • 상한 경계값 (Upper Bound)
      • 이상치 판단기준(최댓값)
    • $Q3 + 1.5 \times \text{IQR}$

    1.2 이상치 판단 기준

    • 이상치(Outlier): 이 범위를 벗어난 값
    • Q1 (1사분위수): 데이터 25% 지점
    • Q3 (3사분위수): 데이터 75% 지점
    • IQR (사분위범위): 데이터 중간 50%의 범위
    • IQR 벗어나면 이상치(Anomaly Data)

    1.3 박스 플롯에서의 이상치 표시 방식

    • 박스(Box): Q1(25%) ~ Q3(75%) 사이의 값 (데이터의 50% 포함)
    • 중앙값(Median, Q2): 박스 내부의 가로선
    • 수염(Whiskers): 이상치를 제외한 데이터의 최대/최소값 연결
    • 이상치(Outlier): 박스 플롯 바깥쪽의 점(●, x)으로 표시

    1.4 IQR을 활용한 이상치 탐지 및 제거 코드 예제

    # 이상치 탐지
    Q1 = df["Ad Clicks"].quantile(0.25)  # 1사분위수
    Q3 = df["Ad Clicks"].quantile(0.75)  # 3사분위수
    IQR = Q3 - Q1  # IQR 계산
    
    # 이상치 제거
    df_filtered = df[(df["Ad Clicks"] >= Q1 - 1.5 * IQR) &
                     (df["Ad Clicks"] <= Q3 + 1.5 * IQR)]
    
    print(df_filtered)
    
    
    • quantile(): 사분위수를 계산하는 함수
    • IQR: 데이터 중간 50%의 범위
    • 이상치 제거: 1.5 * IQR을 기준으로 하한/상한 경계 설정

    1.5 API 통신 중 발생할 수 있는 결측치

    API 통신 중 발생하는 결측치는 데이터베이스에 다음과 같은 방식으로 저장될 수 있다.

    1. NULL 값으로 저장됨 (null 응답).
    2. 빈 문자열로 저장됨 ("" 응답).
    3. 0 또는 기본값으로 저장됨.
    4. 잘못된 데이터 형식으로 저장됨 (예: int 필드에 string).
    5. 필드 자체가 누락되어 NULL로 저장되거나 기본값으로 채워짐.

    데이터베이스에서 결측치를 처리할 때는 다음과 같은 방법을 고려할 수 있다.

    • NULL 값 변환: COALESCE() 함수를 사용하여 NULL 값을 기본값으로 변환.
    • 데이터 타입 검증: API 응답 데이터를 저장하기 전에 데이터 타입을 변환 또는 검증.
    • 기본값 설정: DEFAULT 값을 설정하여 필드가 NULL이 아닐 때 기본값을 자동 삽입.

     

     

    2️⃣ 데이터 변환 (Data Transformation)

    2.1 데이터 변환의 필요성

    • 데이터 정제(Data Cleaning): 결측값, 이상치를 처리하여 신뢰성 있는 데이터 확보
    • 데이터 표준화(Standardization): 분석 및 비교를 위해 일관된 데이터 형식 유지
    • 특성 엔지니어링(Feature Engineering): 새로운 변수 생성으로 인사이트 도출
    • 머신러닝 모델 준비(Model Preparation): 모델 학습을 위한 데이터 전처리

    3️⃣ 데이터 변환 기법

    3.1 결측값 처리 (Handling Missing Values)

    • 결측값: 데이터의 정확도가 낮아지고 왜곡될 가능성 있음
    • 처리 방법:
      • 평균(Mean) 또는 중앙값(Median)으로 대체
      • 결측값 삭제 (dropna())
      • 최빈값(Mode)으로 대체
    #결측치 확
    missing_values_example = df_example.isnull().sum()
    
    # 결측값을 평균(Mean)으로 대체
    df.fillna(df.mean(), inplace=True)
    
    # 중앙값(Median)으로 대체
    df.fillna(df.median(), inplace=True)
    
    # 최빈값(Mode)으로 대체
    df.fillna(df.mode().iloc[0], inplace=True)
    
    #복사해서 사용 시,
    df = df.fillna(df.mean())
    
    #숫자형 데이터에서 `NaN` 값을 해당 열의 평균값으로 대체함.
    df.fillna(df.mean(numeric_only=True))
    
    • 결측치 확인 : isnull() 함수는 데이터프레임(DataFrame) 또는 시리즈(Series)에서 결측치(NaN)를 확인하는 함수입니다. 결과는 각 값이 결측치인지(True) 또는 아닌지(False)를 나타내는 불리언(Boolean) 값으로 반환됩니다.
    • inplace=True는 pandas에서 데이터프레임를 수정할 때, 원본 객체를 직접 변경하도록 설정하는 옵션, 그래서 warning이 뜰 수 있음그래서 데이터 베이스를 복제해서 사용하는게 나음.
    • 평균 대체 vs. 중앙값 대체
    방법  장점  단점  추천 상황
    평균(Mean) 대체 데이터의 전체적인 대표값을 유지 이상치(극단값)가 있으면 왜곡될 가능성 있음 이상치가 적고 정규분포를 따르는 경우
    중앙값(Median) 대체 이상치(극단값)의 영향을 받지 않음 정규분포를 따르는 경우, 평균보다 대표성이 떨어질 수 있음 이상치가 많은 경우

    3.2 데이터 타입 변환 (Data Type Conversion)

    • 문자열을 숫자로 변환 (예: "Yes"/"No" → 1/0)
    • 날짜 데이터를 분석 가능하도록 변환
    # 광고 시청 여부를 0과 1로 변환
    df["Ad Viewed"] = ["Yes", "No", "Yes", "No", "Yes"]
    df["Ad Viewed"] = df["Ad Viewed"].map({"Yes": 1, "No": 0})
    
    # 문자열 데이터를 숫자로 변환
    df["Ad Viewed"] = df["Ad Viewed"].map({"Yes": 1, "No": 0})
    
    # 날짜 데이터 변환
    df["Survey Date"] = pd.to_datetime(df["Survey Date"])
    
    #광고시청여부 컬럼 생성하여 데이터 넣기(문자열)
    #문자열 데이터를 0,1 숫자로 변환(map 메서드 이용)
    #surveydate 컬럼 생성후 날짜형으로 데이터를 바꿔서 저장
    

    3.3 범주형 데이터 변환 (Categorical Encoding)

    • 레이블 인코딩(Label Encoding): 범주형 데이터를 숫자로 변환
    • 원-핫 인코딩(One-Hot Encoding): 범주형 데이터를 여러 개의 이진(0/1) 컬럼으로 변환
    from sklearn.preprocessing import LabelEncoder
    
    # 레이블 인코딩
    le = LabelEncoder()
    df["Campaign_Encoded"] = le.fit_transform(df["Campaign"])
    
    # 원-핫 인코딩
    df_one_hot = pd.get_dummies(df, columns=["Campaign"])
    
    

    예제

    import pandas as pd
    import numpy as np
    from sklearn.preprocessing import LabelEncoder  # 머신러닝을 위한 레이블 인코딩 모듈 (범주형 데이터를 숫자로 변환)
    
    # 📌 1. 예제 데이터 생성 (결측값 포함)
    data = {
        "User ID": [101, 102, 103, 104, 105],  # 고유한 사용자 ID
        "Age": [25, 30, np.nan, 40, 35],  # 사용자의 나이 (결측값 포함)
        "Ad Clicks": [10, 50, 35, 30, 60],  # 광고 클릭 수
        "Conversion Rate": [0.02, 0.05, 0.03, 0.04, 0.07],  # 전환율 (클릭 후 구매 비율)
        "Ad Influence": [5, np.nan, 3, 4, 5],  # 광고 영향력 (결측값 포함)
        "Product Satisfaction": [np.nan, 4, 3, 5, 4],  # 제품 만족도 (결측값 포함)
        "Campaign": ["YouTube Ad", "SNS Ad", "Search Ad", "Email Marketing", "SNS Ad"]  # 광고 캠페인 유형
    }
    
    # 데이터를 pandas DataFrame으로 변환
    df = pd.DataFrame(data)
    
    # 📌 2. 결측값(NaN)을 각 컬럼의 평균값으로 대체 (숫자형 데이터에 대해서만)
    df.fillna(df.mean(numeric_only=True), inplace=True)
    
    # 📌 3. 레이블 인코딩(Label Encoding) - 범주형 데이터를 숫자로 변환
    # - "Campaign" 열의 문자열 값을 숫자로 변환하여 새로운 컬럼 "Campaign_Encoded" 생성
    le = LabelEncoder()  # LabelEncoder 객체 생성
    df["Campaign_Encoded"] = le.fit_transform(df["Campaign"])  # "Campaign" 열을 숫자로 변환
    
    # 📌 4. 원-핫 인코딩(One-Hot Encoding) 적용 - 범주형 데이터를 0,1로 변환
    # - "Campaign" 열을 원-핫 인코딩하여 새로운 컬럼 추가 (ex. Campaign_YouTube Ad, Campaign_SNS Ad 등)
    df_one_hot = pd.get_dummies(df, columns=["Campaign"])
    
    # 📌 5. 최종 결과 출력
    print(df_one_hot)
    
    

     

    정규화 예제 중,

     

    📌 왜 "YouTube Ad"가 2고, "SNS Ad"가 1일까?

    LabelEncoder()는 내부적으로 알파벳 순서(A → Z) 로 정렬한 후, 0부터 차례대로 숫자를 매김.

    1. 원-핫 인코딩(One-Hot Encoding)
      • 범주형 데이터를 0과 1의 이진값으로 변환.
      • 예: "Campaign" 컬럼이 "YouTube Ad", "SNS Ad", "Search Ad" 등의 값을 가진다면,이를 "Campaign_YouTube Ad", "Campaign_SNS Ad", "Campaign_Search Ad" 같은 새로운 컬럼으로 나눠 0 또는 1로 표시함.
      • 장점: 모델이 범주 간 크기 차이를 인식하지 않도록 해줌.
    2. 레이블 인코딩(Label Encoding)
    • 범주형 데이터(문자열)를 숫자로 변환함.
    • 예: "YouTube Ad" → 2, "SNS Ad" → 1, "Search Ad" → 3, "Email Marketing" → 0
    • 단점: 숫자의 크기가 의미를 가지므로(서열 관계로 해석될 수 있음) 머신러닝 모델에 따라 부적절할 수 있음.

    📌 레이블 인코딩과 원-핫 인코딩 비교

    • 레이블 인코딩: Campaign을 하나의 숫자 컬럼(0, 1, 2 등)으로 변환
    • 원-핫 인코딩: Campaign을 여러 개의 컬럼으로 변환하여 0, 1 값으로 표시

    3.4 데이터 스케일링 (Data Scaling)/ 정규화(Normalization) & 표준화(Standardization)

    광고 영향도(Ad Influence), 제품 만족도(Product Satisfaction) 등 연속형 변수는 범위가 다를 수 있다.

    따라서 모델 학습과 비교를 위해 정규화(Normalization) 또는 표준화(Standardization) 적용이 필요하다.

    • 정규화(Normalization): 데이터를 0과 1 사이의 값으로 변환
    • 표준화(Standardization): 평균 0, 표준편차 1의 정규 분포 형태로 변환
    from sklearn.preprocessing import MinMaxScaler, StandardScaler
    
    # 정규화 (Min-Max Scaling)
    scaler = MinMaxScaler()
    df_normalized = pd.DataFrame(scaler.fit_transform(df), columns=df.columns)
    
    # 표준화 (Z-score Scaling)
    scaler = StandardScaler()
    df_standardized = pd.DataFrame(scaler.fit_transform(df), columns=df.columns)
    
    

    fit_transform()은 데이터 학습(fit) + 숫자로 변환(transform)을 한 번에 수행하는 함수


    3.5. 피처 엔지니어링 (Feature Engineering)

    그로스 마케팅에서는 기존 데이터를 가공하여 새로운 인사이트를 얻을 수 있는 변수를 추가하는 것이 중요하다.

    예를 들어, 만족도 점수를 기반으로 고객을 그룹화할 수 있다.

    # 제품 만족도 점수가 4 이상이면 "High", 그렇지 않으면 "Low"
    df["Satisfaction Level"] = df["Product Satisfaction"].apply(lambda x: "High" if x >= 0.8 else "Low")
    
    print(df)
    
    • if는 정규로 안해도 되고 인라인으로 써도됨.(함수내에)

    3.5 로그 변환 (Log Transformation)

    • 설명: 값이 극단적으로 큰 경우, 로그 변환을 사용하여 데이터를 안정화
    • 사용 예시: 광고 비용, 매출액 등 지수 함수 형태의 데이터를 정규화
    import numpy as np
    
    # 로그 변환 적용 (0 방지 위해 1 추가)
    df["Log Ad Cost"] = np.log1p(df["Ad Cost"])
    
    

    3.6 날짜 데이터 변환 (Date Processing)

    • 날짜 데이터를 연/월/일/요일 등으로 분해하여 분석 가능
    • 시간에 따른 트렌드 분석이나 요일별 패턴 확인에 유용
    # 날짜 데이터 추가
    df["Date"] = pd.to_datetime(["2024-02-01", "2024-02-02", "2024-02-03", "2024-02-04", "2024-02-05"])
    
    # 요일 컬럼 추가
    df["Day of Week"] = df["Date"].dt.day_name()
    --------------------------------------------
    
    # 날짜 데이터 변환
    df["Date"] = pd.to_datetime(df["Date"])
    
    # 요일 추가
    df["Day of Week"] = df["Date"].dt.day_name()
    
    # 연도, 월, 일로 나누기
    df["Year"] = df["Date"].dt.year
    df["Month"] = df["Date"].dt.month
    df["Day"] = df["Date"].dt.day
    
    

    4️⃣그로스 마케팅에서 활용되는 데이터 변환 예시

    그로스 마케팅에서는 고객 행동 데이터, 광고 성과 데이터, 전환율 분석 데이터 등 다양한 유형의 데이터를 다룬다.

    효과적인 분석과 모델링을 위해 데이터 변환을 수행해야 하며, 다음과 같은 변환 기법이 활용된다.

    • 결측값 처리 → 광고 클릭, 전환율 등 데이터 손실 방지
    • 데이터 변환 → 숫자 변환, 인코딩, 로그 변환 등을 활용하여 비교 가능하게 변환
    • 스케일링 적용 → 정규화 및 표준화를 통해 광고 비용, 클릭 수 등의 비교 가능
    • 피처 엔지니어링 → 고객 세그먼트, 날짜 기반 변수 등을 추가하여 분석력 향상
    • 이상치 제거 → 광고 효과 분석의 정확성을 높이기 위해 극단값 조정