25.05.19 코딩 공부 시작

코딩 척척석박사 분들 피드백 환영합니다.

공대생이 코딩에서 살아남기

강의자료/데이터 분석 종합반

5강. (05.22) <히트맵, cut>

코딩 아가 2025. 5. 22. 19:05

코호트 차트란?

  • 소비자를 시간의 흐름과 사용하는 서비스의 단계 등으로 나누어 같은 성질의 집단으로 구분한 것
  • 소비자의 전환율을 시간의 흐름과 서비스의 단계나 재사용 등 두 가지 요인을복합적으로 보여줄 수 있는 차트

피벗 테이블이란?

  • 기존의 데이터를 바탕으로 필드를 재구성해, 데이터 통계를 보다 쉽게 파악 할수 있도록 만든 테이블
  • 데이터 분석 결과 한눈에 보기 가능
  • 그래프의 밑작업

리텐션 테이블이란?

  • 고객이 우리 제품이나 서비스를 지속적으로 소비하는 것에 대한 수
  • 좀 더 가시화 가능(비율)

히트맵이란? (Seaborn 사용)

  • 데이터의 값을 색상으로 표현하여, 복잡한 정보를 시각적으로 쉽게 이해할 수 있도록 도와주는 데이터 시각화 기법
  • 2차원 형태의 데이터를 행과 열로 구성된 행렬로 나타내며, 각 셀의 색상은 해당 위치의 데이터 값을 나타낸다.

cmaps = ['plasma', 'Blues', 'coolwarm', 'BuPu', 'Greens', 'Oranges', 'Reds', 'Purples', 'YlOrBr' 등등]

MISSION: 8월 중순부터 완주율이 크게 떨어졌다. 이유를 찾아서 개선해보자!

  • 고객의 입장에서 수업을 듣는 여정 생각해보기 (세부 문제로 나누기)
    1. 강의를 들을 수 있는 시간적 여유가 생긴다. (개입 불가능) - 가설1
    2. 강의를 들어야겠다고 마음을 먹는다. (찐한관리로 개입 가능) - 가설2
    3. 강의를 듣기 위해 콘텐츠에 접근한다. (가정: 오류 없이 접근 가능)
    4. 콘텐츠를 목표한 부분까지 듣는다. (흥미도, 실용성) - 가설3

[가설1]

1) 문제 파악 및 가설 설정하기

  • 문제파악: 2-30대의 강의 구매 건수는 다른 나이대에 비해 높은 편이지만 수강 완료 후 제출하는 퀴즈의 참여율은 저조하다. 이유로 '바빠서'라는 답변이 많았다.
  • 가설1: 다른 연령대에 비해 바쁜 20~30대의 수강 완주율이 상대적으로 낮을 것이다.

2) 데이터 분석 기본 세팅 하기 + 분석하기

import pandas as pd
import matplotlib.pyplot as plt
plt.rc('font', family='NanumBarunGothic')
sparta_data = pd.read_csv('/content/sprata_data.csv')
#나이대별로 수강률 합 구하기
progress_rate_by_age = sparta_data.groupby('age')['progress_rate'].sum()
#나이대별 수강인원 구하기
number_people_by_age = sparta_data.groupby('age')['_id'].count()
#나이대별 완주율 평균 구하기
average = progress_rate_by_age/number_people_by_age

3) 분석 결과 시각화 하기

plt.figure(figsize=(6,6))
#그래프의 x축 눈금 설정
plt.xticks([10,20,30,40,50])
plt.bar(average.index, average,width=8)
#그래프의 바에 각 수치율을 추가
bar = plt.bar(average.index,average,width=8)
for rect in bar:
    height = rect.get_height()
    plt.text(rect.get_x() + rect.get_width()/2.0, height, '%.1f' % height, ha='center', va='bottom', size = 12)
#pad = 타이틀과 그래프와의 간격
plt.title('[나이대 별 평균 수강율]',fontsize=15,pad=10)
#labelpad = 축 레이블과 그래프와의 간격
plt.xlabel('나이',fontsize=12,labelpad=10)
plt.ylabel('수강생(명)',fontsize=14,rotation=0,labelpad=35)
plt.show()

4) 가설1 결론 내리기

데이터 분석 결과, 
2-30대의 평균 수강율이 다른 나이대와 비슷한 비율을 가지고 있다. 가설1 "다른 연령대에 비해 바쁜 20~30대의 수강 완주율이 상대적으로 낮을 것이다."은 틀렸다.

결론: 강의 개선이나 광고 메인 타겟 변경은 필요하지 않을 것 같다.

[가설2]

1) 문제 파악 및 가설 설정하기

  • 문제파악: 최근 3개월간 찐한관리 신청 비율과 완주율이 모두 감소하고 있다.
  • 가설2: 찐한관리를 받은 인원이 그렇지 않은 인원보다 완주율이 높을 것이다.

2) 데이터 분석 기본 세팅 하기 + 분석하기

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
plt.rc('font', family='NanumBarunGothic')
sparta_data = pd.read_csv('/content/sprata_data.csv')
# 데이터 수정하기
managed = ['TRUE','FALSE'
#관리 여부에 따라, 수강완료율 평균 구하기
managed_data_avg = sparta_data.groupby('managed')['progress_rate'].sum()/sparta_data.groupby('managed')['_id'].count()

3) 분석 결과 시각화 하기

plt.bar(managed_data_avg.index,managed_data_avg)
bar = plt.bar(managed_data_avg.index ,managed_data_avg)
for rect in bar:
    height = rect.get_height()
    plt.text(rect.get_x() + rect.get_width()/2.0, height, '%.1f' % height, ha='center', va='bottom', size = 12)
plt.title('[찐한관리 유무에 따른 평균 완주율]',fontsize=14)
#기존 x축 레이블 0,1을 labels =["..."]로 변경
plt.xticks([0,1], rotation=0,labels=["찐한관리 비 신청자","찐한관리 신청자"])
plt.xlabel('평균 완주율',fontsize=12)
plt.ylabel('찐한관리 여부',fontsize=12,rotation=360,labelpad=35)
#그래프를 화면에 나타나도록 합니다.
plt.show()

4) 가설2 결론 내리기

데이터 분석 결과, 
찐한 관리를 받는 수강생들의 완주율이 거의 2배 가까이 높은 것을 확인 할 수 있다. 가설2 " 찐한관리를 받은 인원이 그렇지 않은 인원보다 완주율이 높을 것이다. "은 옳다.

결론: 찐한 관리 참여를 적극적으로 유도해야한다.

[가설3]

1) 문제 파악 및 가설 설정하기

    • 문제파악: 8월 중순에 강의 개선이 이루워졌는데 그 시점에 완주율이 낮아졌다. 
    • 가설3: 8월 둘째 주 부터 변경된 3주 차 강의의 완주율이 현저히 떨어졌을 것이다.

2) 데이터 분석 기본 세팅 하기 + 분석하기

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
plt.rc('font', family='NanumBarunGothic')
sparta_data = pd.read_csv('/cohort_data.csv')
#sparta_data = pd.read_table('/cohort_data.csv',sep=',')
#수강 시작 날짜 문자에서 숫자로 변경하기
format='%Y-%m-%dT%H:%M:%S.%f'
sparta_data['start_time'] = pd.to_datetime(sparta_data['created_at'], format='mixed')
#수강 시작 주 구하기
sparta_data['start_week']= sparta_data['start_time'].dt.isocalendar().week

#처음 수강 시작한 주 범위 확인 하기
#set=중복 없는 고유한 요소만
category_range = set(sparta_data['start_week'])
#진도율
progress_rate = list(sparta_data['progress_rate'])
#진도율을 강의 주차로 변경 하기
  • 0주차 : 0 ~4 .11%
  • 1주차 : 4.12% ~ 26.03%
  • 2주차 : 26.04% ~ 41.10%
  • 3주차 : 41.11% ~ 61.64%
  • 4주차 : 61.65% ~ 80.82%
  • 5주차 : 80.83% ~ 100%
#bins = 범주 표현(처음(0)과 끝(100) 잊지 말기)
bins = [0,4.11,26.03,41.10,61.64,80.82,100]
#구분한 범주의 라벨 labels
labels=[0,1,2,3,4,5]
#pd.cut = 범주화에 사용하는 함수 
cuts= pd.cut(progress_rate,bins, right=True,include_lowest=True, labels=labels)

#결과물을 테이블로 변경하기
cuts = pd.DataFrame(cuts)
#concat() = 표 합치기
sparta_data = pd.concat([sparta_data,cuts],axis=1, join='inner')
#표 인덱스 변경하기
sparta_data.columns=['created_at','user_id','name','progress_rate','start_time','start_week',"week"]
#시작주와, 수강 주차별 기준으로 표 grouping 하기
grouping = sparta_data.groupby(['start_week','week'])
grouping.head()

#시작주와, 수강 주차별에 해당하는 수강생 수 구하기
cohort_data = grouping['user_id'].apply(pd.Series.nunique)
cohort_data = pd.DataFrame(cohort_data)
#첫 주차 = 31
f=31
#range(6) start_week범위가 {31,32,33,34,35,36}
#강의는 5~0주차, 1씩감소
for j in range(5, 0, -1):
    cohort_data.at[(f,j-1), 'user_id'] = int(cohort_data.at[(f,j),'user_id']) +  int(cohort_data.at[(f,j-1),'user_id'])
 #주차는 31~36주차, 1씩증가
  f=f+1
cohort_data  #표1
#인덱스 새로 설정
cohort_data = cohort_data.reset_index()
cohort_data  #표2
#피벗 테이블
cohort_counts = cohort_data.pivot(index="start_week",columns="week",values="user_id")
cohort_data  #표3
#리텐션 테이블
retention = cohort_counts
#각 주(week) 별 최초 수강생 수만 가져오기 (나눠줄때, 분모가 되는 부분!)
cohort_sizes = cohort_counts.iloc[:,0]
cohort_sizes.head()
# 표의 단일 데이터에 최초 수강생의 수를 나누어, 각 주당 수강생 수강율 나타내기!
retention = cohort_counts.divide(cohort_sizes, axis=0)
retention.head()
#각 수치 퍼센트로 변경하기(round(3) = 소수점 3자리 수에서 반올림 한 후, 100을 곱하기)
retention.round(3)*100  #표4

 

3) 데이터 시각화하기

#annot = 각 cell의 데이터 표기 유(True)/무(False)
#fmt = '.0%' 데이터값의 소수점 0까지 표기
#vmin = 최소값 설정
#vmax = 최댓값 설정
#cmap = 히트맵의 색
plt.figure(figsize=(10,8))
sns.heatmap(data=retention,
           annot=True,
           fmt='.0%', #values(데이터의 값) 값의 소수점 표기
           vmin=0,#최소값 설정
           vmax=1,#최댓값 설정
           cmap="plasm" #히트맵의 색을 설정합니다
            )
plt.xlabel('주차', fontsize=14,labelpad=30)
plt.ylabel('개강일', fontsize=14,rotation=360,labelpad=30)
plt.yticks(rotation=360)
plt.show()

4) 가설3 결론 내리기

데이터 분석 결과, 
3주차에서 4주차에 도달하는 인원만 떨어진게 아니라 전체적으로 떨어졌다. 가설3 "8월 둘째 주 부터 변경된 3주 차 강의의 완주율이 현저히 떨어졌을 것이다." 은 틀렸다.

결론: 강의 개선이 아닌 다른 요인이 완주율을 낮추었다.

숙제

MISSION: 가설3의 코호트 차트를 더 잘 보아게 만들어보기(각 주차마다 출발선 같게 만들기)

#주차별 수강 전환율 구하기
w=31
for i in range(6):
  for j in range(5, 1, -1):
    retention.at[(w,j)] = retention.at[(w,j)]/retention.at[(w,j-1)]
  w=w+1

'강의자료 > 데이터 분석 종합반' 카테고리의 다른 글

4강. (05.21)  (0) 2025.05.21
3강. (05.20)  (6) 2025.05.20
2강. (05.19)  (0) 2025.05.20
1강. (05.19)  (1) 2025.05.19