[데이터분석] 부트캠프 TIL

20260320 TIL

myun0506 2026. 3. 20. 21:21

[Today I Learn]

- 실전 프로젝트 EDA


[ 실전 프로젝트 EDA ]

1. pd.concat()

  • 여러 DataFrame을 위아래(axis=0) 또는 **좌우(axis=1)**로 단순 결합하는 함수
  • merge와 달리 키 매칭이 아닌 인덱스 순서 기반으로 결합
  • axis=1 사용 시 두 DataFrame의 인덱스가 다르면 NaN 발생 → 반드시 reset_index() 확인
  • axis=0 사용 시 인덱스 꼬임 방지를 위해 ignore_index=True 사용
  • 💡 apply()로 생성한 Series 객체는 원본 인덱스를 그대로 유지하므로, concat 시 인덱스 정렬 걱정 없음

2. np.where()

  • np.where(조건, 참, 거짓) → 조건부 값 선택 (SQL의 CASE WHEN, Excel의 IF와 동일)
  • 인자 1개만 넣으면 → 조건을 만족하는 인덱스 반환
  • 실무 활용: 파생 변수 생성, 이상치 처리(Winsorizing), 0 나눗셈 방지
  • 다중 조건(3가지 이상)은 중첩 np.where 또는 np.select() 사용
  • ⚠️ 주의: 양쪽 값(x, y)을 모두 먼저 계산하므로 0 나눗셈 시 RuntimeWarning 발생 가능 (결과는 정상)
  • 벡터화 연산이라 for문·apply()보다 훨씬 빠름

 

📌 실전프로젝트 전처리 2 요약

🔧 전처리 주요 변경사항 (4가지)

# 이슈 문제 설명 결정

1 멤버십 데이즈 컬럼 보정값(프록시) 사용 중 제거 → 가입 연월(코호트) 추출로 변경
2 person / customer_id 중복 두 컬럼이 완전히 동일한 값 person → customer_id로 rename, 기존 코드 삭제
3 viewed_before_complete 시점 미반영 구매 후 쿠폰 확인도 1로 표시됨 시점 비교 기반 is_aware 컬럼으로 대체
4 나이·성별 컬럼 미생성 분석에 필요한 파생변수 없음 age_group, age_gender 두 컬럼 모두 생성·유지

1. 멤버십 데이즈 컬럼 처리

  • 기존: 멤버십 데이즈를 보정값(프록시)으로 사용
  • 변경: 컬럼 제거 → 실제 가입일(became_member_on)에서 연도/월 직접 추출
  • 💡 절대 날짜가 있으므로 프록시 값은 불필요한 오차만 유발

2. Person / Customer ID 중복 제거

  • ADFF 파일에서 person과 customer_id가 동일한 값임을 확인
  • person → customer_id로 rename, astype(str)로 타입 통일
  • 💡 실무 팁: 전처리 초기에 .nunique() 또는 .equals()로 컬럼 간 중복 여부 반드시 확인

3. Viewed Before Complete → is_aware 로직 개선

  • 🚨 기존 문제: 단순 뷰 발생 여부만 카운트 → 시점 미반영 → 체리피커 식별 오류
    • A 고객: 10시 쿠폰 확인 → 14시 구매 (마케팅 성공) → 기존·새 로직 모두 정확
    • B 고객: 14시 구매 → 15시 쿠폰 확인 (마케팅 효과 없음) → 기존 로직은 오류로 1 표시, 새 로직은 False로 정확 판별
  • 새 로직 흐름:
    1. View 테이블 / Complete 테이블 별도 생성
    2. Complete 기준 Left Merge (뷰 없는 구매도 포함)
    3. is_aware = time_view < time_comp → 뷰가 구매보다 먼저면 True
    4. 정렬: customer_id(오름) → time_comp(오름) → is_aware(내림, True 우선) → time_view(내림, 구매 직전 조회 우선)
    5. drop_duplicates(keep='first') → 가장 의미 있는 뷰-구매 쌍만 남김
  • 결정: 기존 viewed_before_complete 삭제, is_aware로 대체

4. 나이 및 성별 그룹 컬럼 생성

  • age_group: 20대 미만 / 20대 / 30대 / 40대 / 50대 / 60대 이상 / 누락(NaN)
  • age_gender: 연령대 × 성별 조합 (예: "30대 남성", "50대 여성")
    • gender == 'Unknown' 또는 age NaN → "미기입"
    • gender == 'O' → "Others"
  • 💡 분석 초기에는 파생변수를 최대한 많이 생성해두고, 발표 시 필요에 따라 선택 사용

✅ 오늘의 핵심 요약 3줄

  1. 전처리에서 컬럼 중복(person/customer_id)과 같은 데이터 품질 이슈는 초기에 .equals() 등으로 반드시 검증해야 한다.
  2. 마케팅 효과 측정 시 단순 이벤트 발생 여부가 아닌 시점(타이밍)을 반영한 is_aware 로직으로 체리피커를 정확하게 식별할 수 있다.
  3. 파생변수(age_group, age_gender)는 분석 초기에 최대한 생성해두고, 절대 날짜가 있다면 프록시 값 대신 직접 추출하는 것이 원칙이다.

 

📌 실전프로젝트 EDA 요약

1. 마케팅 효과 확인 (is_aware 플래그)

  • offer viewed → offer completed 순서인지를 기준으로 마케팅 인지 여부(is_aware) 를 판별
    • is_aware == True : 오퍼를 인지한 후 구매 → 마케팅 효과 있음
    • is_aware == False : 오퍼를 보기 전에 이미 구매했거나, 오퍼 존재를 모른 채 구매 → 마케팅 효과 없음
  • merge → sort_values → drop_duplicates로 고객×오퍼×완료 시점 기준 1건만 남김 (완료 직전 가장 가까운 조회 기록 매칭)

2. 오퍼별 추가 분석

  • 오퍼 마스터 테이블에 received_count, aware_rate(인지율) 등을 합쳐 분석
  • 보상 효율성 지표: reward_ratio = reward / difficulty, offer_strength = reward - difficulty
  • 오퍼 매력도(reward_ratio, offer_strength)와 aware_rate 간 상관관계 확인

3. 채널별 인지율 분석

  • is_aware == True / False 그룹별로 ch_web, ch_email, ch_mobile, ch_social 평균 비교
  • 소셜 채널(ch_social)이 인지율이 높게 나왔지만, 해당 오퍼들의 보상이 컸던 것은 아닌지 교차 검증 필요
  • 채널 개수(channel_count)가 많을수록 인지율이 높아지는 경향 확인
    • 2채널: 41.1% → 3채널: 55.9% → 4채널: 79.6%

4. 인지율 vs 전환율 개념 정리

  • 인지율(Awareness Rate) = 인지하고 완료한 수 / 전체 완료한 수 → "구매자 중 오퍼를 알고 산 비중"
  • 전환율(Conversion Rate) = 인지하고 완료한 수 / 전체 인지(View)한 수 → "오퍼를 본 사람 중 실제 구매 비율"

5. 남은 분석 과제

  • ch_social 포함인데 is_aware == False인 데이터 → 연령대·소득 수준과 소셜 미디어 활용도 관계 확인
  • 고객별 완료/수신 비율, 조회/수신 비율 산출
  • 고객군 분류: reward_ratio 높은 오퍼만 사용하는 체리피커 vs 오퍼 무관하게 구매하는 브랜드 충성 고객

'[데이터분석] 부트캠프 TIL' 카테고리의 다른 글

20260325 TIL  (0) 2026.03.25
20260324 TIL  (0) 2026.03.24
20260318 TIL  (0) 2026.03.18
20260317 TIL  (0) 2026.03.17
20260316 TIL  (1) 2026.03.16