데이터분석 | 완주율을 높이는 요인 | 적절한 타겟 설정 | 프로덕트 개선

    728x90

     

    수강 완주율 개선

     

    0. 가설 설정하기

     

    ▶ 가설1 : 우리는 적절한 타겟에게 판매를 하고 있을까?

    다른 연령대에 비해 바쁜 20~30대의 수강 완주율이 상대적으로 낮을 것

    완주가 가능한 수강생들이 수강을 할 수 있도록 적절한 포지셔닝을 고민해야 함

    • 나이대 별 완주율 평균 구하기

    1. 분석할 데이터 가져오기

     

    ▶ 한글 깨짐 방지 코드

    !sudo apt-get install -y fonts-nanum
    !sudo fc-cache -fv
    !rm ~/.cache/matplotlib -rf

     

    ▶ 라이브러리 가져오기

    import pandas as pd
    import matplotlib.pyplot as plt
    plt.rc('font', family='NanumBarunGothic') #한글 깨짐 방지 설정

     

    ▶ 스파르타 데이터 읽어오기

    sparta_data = pd.read_csv('/content/sprata_data.csv')

     

    • _id : 회원 고유 아이디
    • created_a t: 수강 등록 시점
    • updated_at : 최근 수강 완료 시점
    • name : 회원 이름
    • marketing : 마케팅 수신동의
    • managed : 찐한 관리 여부 (수강 동기부여 메시지 수신 등 관리 받을지 여부)
    • gender : 성별
    • age : 나이대
    • progress_rate : 진도율

    2. 데이터 전처리 및 분석하기

     

    ▶ 나이대 별 수강률 합 구하기

    progress_rate_by_age = sparta_data.groupby('age')['progress_rate'].sum()

    progress_rate_by_age

     

    ▶ 나이대 별로 수강인원 구하기

    number_people_by_age = sparta_data.groupby('age')['_id'].count()

    number_people_by_age

     

    ▶ 나이대 별 완주율 평균 구하기

    average_progress_rate = progress_rate_by_age/number_people_by_age

     

    average_progress_rate


    3. 데이터 시각화하기

     

    ▶ 분석한 데이터 시각화하기

    # plt.figure(width, height) 
    plt.figure(figsize=(6,6))
    
    # 그래프의 x축 눈금 설정
    plt.xticks([10,20,30,40,50])
    
    # plt.bar(X축값, Y축값)
    plt.bar("x축", "y축")
    
    
    # 그래프의 각 막대에 수치 추가하기
    bar = plt.bar(average_progress_rate.index, average_progress_rate,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=20)
    
    # 그래프 x축 라벨 이름
    # labelpad 파라미터로 축 레이블 여백 지정
    plt.xlabel('나이', fontsize=12, labelpad=20)
    
    # 그래프 y축 라벨 이름
    plt.ylabel('수강생(명)', fontsize=14, rotation=360, labelpad=35)
    
    # 그래프 화면에 나타내기
    plt.show()


    4. 최종 결론

     

    ▶ 결론1

    20~30대의 완주율이 상당히 높음. 잘못된 타겟팅을 한 것은 아님


    0. 가설 설정하기

     

    ▶ 가설2 : 찐한 관리를 하면 완주율이 높아질까?

    최근 3개월간 찐한 관리 신청 비율과 완주율이 모두 감소하는 중

    때마침 8월 중순부터 웹개발 종합반의 완주율도 크게 떨어지고 있음

    찐한 관리와 완주율이 동시에 감소했으므로 연관이 있을 것

    • 찐한관리를 받은 인원그렇지 않은 인원보다 완주율이 높을 것

    1. 분석할 데이터 가져오기

     

    ▶ 라이브러리 가져오기

    import pandas as pd
    import seaborn as sns
    import matplotlib.pyplot as plt
    plt.rc('font', family='NanumBarunGothic')

     

    ▶ 분석할 데이터 가져오기

    sparta_data = pd.read_table('/content/sprata_data.csv', sep = ',')

    sparta_data.head()


    2. 데이터 전처리하기

     

    ▶ True와 False를 문자로 만들어주기

    managed = ['TRUE','FALSE']

    managed


    3. 데이터 분석하기

     

    ▶ 관리 여부에 따른 수강 완료율 평균 구하기

    : 관리 여부 별 완주의 합 ÷ 관리 여부 별 완주자 수

    managed_data_avg = sparta_data.groupby('managed')['progress_rate'].sum()/sparta_data.groupby('managed')['_id'].count()

    managed_data_avg


    4. 데이터 시각화하기

     

    ▶ 분석한 데이터 시각화하기

    # plt.figure(width, height)
    plt.figure(figsize=(6,6))
    
    # plt.bar(X축값, Y축값)
    plt.bar("x축 기입" ,"y축 기입")
    
    # 그래프의 각 막대에 수치 추가하기
    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축 라벨 이름
    plt.xlabel('평균 완주율', fontsize=12)
    
    # x축 눈금 레이블 지정하기
    # 기존의 0, 1이라는 x축 레이블을 labels =["..."]로 변경 가능
    plt.xticks([0,1], labels=["찐한관리 비 신청자", "찐한관리 신청자"])
    
    # 그래프 y축 라벨 이름
    plt.ylabel('찐한관리 여부', fontsize=12, rotation=360, labelpad=35)
    
    # x축 눈금의 글씨 45도 회전
    plt.xticks(rotation=45)
    
    # y축 눈금의 글씨 360도 회전
    plt.yticks(rotation=360)
    
    # 그래프 화면에 나타내기
    plt.show()

     


    5. 최종 결론

     

    ▶ 결론2

    찐한 관리 신청자들그렇지 않은 신청자들에 비해 완주율이 높음

    완주율을 높이기 위해서는 찐한관리 신청을 높일 수 있게 독려해야


    0. 가설 설정하기 

     

    ▶ 가설3 : 프로덕트 개선은 정말 도움이 되었을까?

    웹개발 종합반의 완주율이 8월부터 떨어진 것이

    8월 둘째주 개강반부터 개편된 웹개발 종합반의 3주차 강의로 인한 것인가?

    • 각 개강반 별, 각 수강 주차 별 해당하는 수강생 수를 바탕으로 테이블 만들기
    • 피벗테이블의 각 데이터를 초기 고객수로 나눠 비율로 나타내기

     

    [코호트 분석]

    - 모든 다른 변인들이 통제된 상태에서 각 집단 별로 특정 변수만 바꾸었을 때 나오는 결과를 분석하는 것

    - 시간의 흐름과 사용하는 서비스의 단계 등으로 소비자를 나누어 같은 성질의 집단으로 구분한 것코호트라고 하고,

    소비자의 전환율을 시간의 흐름과 서비스의 단계 등의 두 가지 요인으로 복합적으로 보여줄 수 있게 만든 차트코호트 차트라고 함


    1. 분석할 데이터 가져오기

     

    ▶ 라이브러리 가져오기

    import pandas as pd
    import seaborn as sns
    import matplotlib.pyplot as plt
    plt.rc('font', family='NanumBarunGothic')

     

    ▶ 코호트 데이터 읽어오기

    sparta_data = pd.read_table('/content/cohort_data.csv',sep=',')

    sparta_data.head()

     

    • created_at : 수강 등록 시점 (몇 주차 개강반이었는지)
    • user_id : 수강생 고유 id
    • name : 수강생 이름
    • progress_rate : 진도율

     

    sparta_data.info()

     


    2. 데이터 전처리하기

     

    2-1) created_at (수강 등록 시점)을 일(day) 단위 → 주(week) 단위로 바꾸기

     

    ▶ created_at 데이터의 타입 확인하기

    print(type(sparta_data['created_at'][1]))

    str 문자형

     

    ▶ created_at 데이터를 날짜 타입으로 바꾸기

    format='%Y-%m-%dT%H:%M:%S.%f'
    sparta_data['start_time'] = pd.to_datetime(sparta_data['created_at'], format=format,infer_datetime_format=True)

     

    ▶ start_time 데이터에서 수강 시작 '주(week)' 열 추가하기

    : dt.isocalendar().week 는 날짜를 주로 변경할 때 사용함

    sparta_data['start_week']= sparta_data['start_time'].dt.isocalendar().week

     

    ▶ 처음 수강을 시작한 주의 범위 확인하기

    : set()으로 중복 값을 제거해서 해당 목록에 어떤 값이 들어있는지 확인하기

    category_range = set(sparta_data['start_week'])

    >> 총 6개 주차의 개강반이 있는 것을 확인할 수 있음


    2-2) 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%

     

    ▶ 진도율 데이터를 리스트로 만들기

    progress_rate = list(sparta_data['progress_rate'])

    ..쭉 나옴

     

    ▶ 범주를 구하는 기준 리스트 만들기

    : 범주를 구분하는 기준(bins)의 처음(0)과 끝(100)도 잊지말고 적어주기
    : 구분한 범주의 라벨도 적어주기

    bins = [0, 4.11, 26.03, 41.10, 61.64, 80.82, 100]
    labels=[0,1,2,3,4,5]

     

    ▶ 진도율에 따른 주차 구하기

    : pd.cut() 함수로 범주화하기

    cuts = pd.cut(progress_rate, bins, right=True, include_lowest=True, labels=labels)

    cuts

     

    ▶ 결과물을 테이블로 변경하기

    cuts = pd.DataFrame(cuts)

    cuts


    2-3) sparta_data 테이블과 cuts 테이블 병합하기

     

    concat() 함수 사용

    sparta_data = pd.concat([sparta_data,cuts],axis=1, join='inner')

    >> cuts 테이블이 병합되면서 컬럼 이름이 0으로 됨. 컬럼 이름 바꿔줘야 함

     

    ▶ 컬럼 이름 바꿔주기

    : 컬럼 이름 바꾸고 싶을 때는 전체 컬럼 이름을 다 적어줘야 함

    sparta_data.columns=['created_at','user_id','name','progress_rate','start_time','start_week',"week"]


    3. 데이터 분석하기

     

    ▶ start_week (수강 시작 주)와 수강 중인 주차(week) 기준으로 테이블 만들기

    : 기존의 테이블을 start_week와, week로 묶어주기

    grouping = sparta_data.groupby(['start_week','week'])

    grouping.head()

    >> 겉보기에는 별 다른 게 없어보이지만 179개로 그룹화 됨.

     

    ▶ 시작 주차 별, 수강 중인 주차 별 수강생 수 구하고 테이블로 만들기

    cohort_data = grouping['user_id'].apply(pd.Series.nunique)
    cohort_data = pd.DataFrame(cohort_data)

    cohort_data.head(20)

     

    ▶ 수강 시작 주차 별로 수강한 총 인원 구하기

    : 지금 위에서 수강 중인 주차 별로 구해진 수강생 수는 그 주차에 머무르고 있는 수강생만 더해진 숫자임.

    즉, 수강한 총 인원을 구하기 위해서는 해당 주차의 수강생만큼이 그 앞 전 주차에 계속 더해져서 0주차까지 도달해야 함. 

    다 더해진 0주차의 값이 수강한 총 인원이 될 것.

    : at() 함수를 이용하면 테이블의 하나의 데이터에 접근할 수 있음

    # 첫 주는 31주, 변수를 하나 만들어 줌
    f=31
    
    # 처음 수강 시작한 주의 범위가 {31,32,33,34,35,36} 이니까 range(6)
    for i in range(6):
    	#5주차 강의가 마지막이고, 0주차까지 이니, 시작은 5에서 시작해 1씩 0까지 감소
      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부터 32 33..) 1씩 늘어나죠?
      f=f+1
    
    # 인덱스 새롭게 설정하기
    cohort_data = cohort_data.reset_index()

    cohort_data.head()


    4. 데이터 시각화하기

     

    4-1) 피벗테이블 만들기

     

    ▶ 피벗테이블 만들기

    cohort_counts = cohort_data.pivot(index="start_week",
                                      columns="week",
                                      values="user_id")

    cohort_counts

    >> 개강 주차 별로 수강 시작 인원이 다 다르기 때문에 시간이 지나면서 수강생 수가 얼마나 줄었는지를 정확히 알아보려면 비율을 구해야 함. 

     

    [리텐션 테이블]

    고객이 우리 제품이나 서비스를 얼마나 지속적으로 소비하는지를 보여주는 테이블

    이 테이블을 통해 고객의 행동이 얼만큼 변화하고 있는지를 볼 수 있음

     

    ▶ 수강 첫 주 총 인원 구하기

    : 비율을 구하기 위해서는 '수강 첫 주 총 인원'으로 '각 수강 주차 별 인원'을 나눠주면 됨

    # 앞서 만든 cohort_counts 데이터는 retention 변수에 넣어주기
    retention = cohort_counts
    
    #각 주(week) 별 최초 수강생 수만 가져오기
    cohort_sizes = cohort_counts.iloc[:,0]     # iloc(모든행, 0번째 열)

    cohort_sizes

     

    ▶ 각 주 당 수강생 수강율 구하기

    : cohort_counts 데이터에 앞서 구한 최초 수강생 수를 나누어, 각 주당 수강생 수강율 나타내기

    retention = cohort_counts.divide(cohort_sizes, axis=0)

    retention.head()

     

    ▶ 수강율을 %로 바꾸기

    : 각 수치 퍼센트로 변경하기

    : round() 함수로 3자리 수에서 반올림 한 후, 100 곱해주기

    retention.round(3)*100

    retention


    4-2) 히트맵 만들기

     

    ▶ 분석한 결과로 히트맵 만들기

    #테이블 크기 설정 하기
    plt.figure(figsize=(10,8))
    
    sns.heatmap(data=retention,
               annot=True,       # 각 cell의 데이터 표기 유무를 나타냄
               fmt='.0%',        # values(데이터의 값) 값의 소수점 표기
               vmin=0,           # 최소값 설정
               vmax=1,           # 최댓값 설정
               cmap="BuGn"       # 히트맵 색 설정
    						)
    
    plt.xlabel('주차', fontsize=14, labelpad=30)
    
    plt.ylabel('개강일', fontsize=14, rotation=360, labelpad=30)
    plt.yticks(rotation=360)
    
    plt.show()


    5. 최종 결론

     

    ▶ 결론3

    8월 둘째 주 개강반부터 3주차 강의의 개편이 있었고, 그 때부터 완주율이 떨어졌기 때문에 이 둘의 연관관계가 있을 것이라고 생각함. 이 가설대로라면 개편된 3주차 강의 이후인 4주차의 결과값이 많이 떨어졌어야 함.

    그런데 4주차의 결과값을 보니 모든 개강반의 4주차 완주율이 전보다 떨어지긴 했지만 결과값이 일관적으로 떨어진다기 보다는 오르락 내리락 하고 있음.

    즉, 딱히 3주차의 강의 개편이 완주율에 영향을 주고 있는 것 같지는 않음

    따라서 개편된 3주차는 그대로 놔둬도 될 것으로 생각됨

    728x90

    댓글