카테고리 없음

내일배움캠프_데이터분석종합반_5주차강의

iron-min 2025. 9. 12. 18:17

강의내용 정리

강의 내용중 어려운 내용을 정리해보았습니다.

 

  • 고객이 수강을 완료할 수 있도록 흥미롭고 도움이 되는 콘텐츠를 제공해야 합니다.
  • 8월 중순부터 웹개발 종합반의 완주율이 크게 떨어진 이유를 밝혀야 합니다.

우선 데이터를 확인합니다.

#라이브러리 불러오기
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을 보면

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

날짜 형식이 아닌 문자열인것을 알 수 있습니다.

날짜 형식으로 바꿔주기 위해서

format = "%Y. %m. %d"
sparta_data['start_time'] = pd.to_datetime(sparta_data['created_at'], format='mixed')
sparta_data.tail()

 

to_datetime[데이터(바꿀 컬럼),format='바꿀 형식') 코드를 적용해 줍니다.

 

날자 형식의 컬럼 'start_time'이 생성되었습니다.

 

이제 start_time을 ~주차 형식으로 나타내 주기위해

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

dt.isocalendar().week 으로 날짜를 주로 바꿔줍니다.

여기서 week을 day 또는 year로 변경해줄 수 있습니다.

이제 시작한 주의 데이터를 확인하는 방법입니다.

#이전에 배웠듯이 set()은 set안의 데이터는 순서가 정해져있지 않고, 중복되지 않는 고유한 요소를 가져옵니다!
category_range = set(sparta_data['start_week'])
category_range

set으로 중복되지 않은 고유요소를 가져올 수 있습니다.

31~36주차 까지 총 6개의 리스트를 볼 수 있습니다.

그러면 우리는 주차별 진도율을 확인해봐야 함으로 progress_rate을 리스트로 만들어야 합니다.

progress_rate = list(sparta_data['progress_rate'])
progress_rate

이런식으로 길게 진도율을 확인할 수 있습니다.

0주차 부터 5주차 강의까지 %로 나타낸 주어진 자료입니다.

그리고 이 진도율을 레이블화 하는 방법입니다.

#범주를 구분하는 기준 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=labes)
cuts

bin을 보면 0~4.11 , 26.03~41.10, 61.64~80.82, 80.82~100 까지 구간을 정해주고

labels를 통해 0,1,2,3,4,5 주차 라벨을 만들어줍니다.

 

그리고 이둘을 cut('범주화 할 데이터','구간설정','오른쪽 경계선을 포함하는 구간을 설정할건지','가장 낮은 값을 첫번째 구간에 포함할 건지,각 구간의 설정) 명령어로 묶어줍니다.

 

cuts을 출력하면

이런식으로 각 수강진도율이 ~주차로 묶인것을 확인할 수 있습니다.

명확하게 보기 위해 테이블화 하면

cuts = pd.DataFrame(cuts)
cuts

이렇게 학생이 몇주차를 듣고있는지 보입니다.

이 테이블을 원래의 sparta_data에 병합해주려면

#concat() 함수를 이용하여, sparta_data 테이블과, cuts 테이블 병합 할수 있습니다 :)
sparta_data = pd.concat([sparta_data,cuts],axis=1, join='inner')
sparta_data.head()

이런식으로 concat([병합하려는 테이블1,병합하려는테이블2],열의방향,교집합) 을 이용해서 합쳐주면  

이렇게 합쳐집니다.

컬럼의 이름이 0으로 되어있으니

#그래서, 귀찮더라도, 우리가 원하는 컬럼의 이름을 다 작성해 줍시다!
sparta_data.columns=['created_at','user_id','name','progress_rate','start_time','start_week',"week"]
sparta_data.head()

columns을 이용해 컬럼명을 지정해줍니다.

 

다시 groupby를 이용해 start_week과 week을 묶어줍니다.

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

 

그리고 

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

위 코드를 해석해보면

이미 그룹화된 grouping 컬럼에서 user_id 열만 선택하고

 

pd.Series.nunique는 고유한 값을 세는 Pandas함수라고 하네요.

예를 들면 [1,2,3,4]라는 리스트에 nunique()을 적용하면 3(1,2,3) 이 반환됩니다.

 

그리고 pd.DataFrame(cohort_data) 는 이전 단계에서 계산된 결과를 cohort_data라는 데이터프레임으로 변환하는 것입니다.

잘 이해안되서 지워보고 출력도 했는데 뭐가다른지는 모르겠습니다...

 

 

어쨋든 요런식으로 출력됩니다.

 

그런데 위 표는 주차에 머물러 있는 학생의 수입니다.

즉 4주차를 완료한 학생은 1,2,3 주차 학습도 하였음으로 이를 재귀함수로 표현해줘야합니다.

#첫 주가 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

for문으로 이렇게 재귀함수를 만들어 줍니다.

for 변수 in 반복할_대상

 

첫번째 주차는 31주차로

총 6개의 주차이니 range에 6(6번반복)을 넣어줍니다.

그리고 강의는 총 0에서 5주차 까지 있으니 range(끝,시작,감소) 를 지정해줍니다.

int는 정수를 만들어주는 함수입니다.

 

그러면 이제 핵심부분을 보겠습니다.

cohort_data.at[(f,j-1)은 cohort_data에서 주차에 수업을 시작한 수와 f주차 강의에 머물러 있는 'user_id'를 가져옵니다.

 

.at함수는 ~행 ~열을 지정해줍니다.

그러면 'user_id' f행 j-1열 =  'user_id' f열 j행 +  'user_id' f열 j-1행 이되고 이는 재귀함수로 다시 연산에 들어가게 됩니다.

(밑줄친 부분이 재귀함수 부분이죠) 

 

cohort_data = cohort_data.reset_index()
cohort_data.head()

 

 

이렇게 시작 주와 현재 머물러있는 강의 주차가 표시되게 됩니다.

 

이제 이걸 바탕으로 피벗테이블을 만들어 줍니다.

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

 

 

그리고 표를 퍼센트로 바꿔주기 위한 작업입니다.

# 앞서 만든 피벗 테이블을 retention 변수에 저장하기
retention = cohort_counts

#각 주(week) 별 최초 수강생 수만 가져오기 (나눠줄때, 분모가 되는 부분!)
cohort_sizes = cohort_counts.iloc[:,0]
cohort_sizes.head()

 

여기서 .iloc[:,0] 은 모든 행의 첫번째 문자열만 가져오라는 뜻입니다.

그러면 이렇게 첫번째 문자열을 가져오게 됩니다.

이제 이 첫번째 열로 나머지 열을 나눠주면 되는데

retention = cohort_counts.divide(cohort_sizes, axis=0)
retention.round(3)*100

 

.divide('데이터 프레임을', 행방향)으로 나누라는 표현입니다.

이러면 첫번째 열로 cohort_counts 전체를 행으로 나누게 되겠죠

그리고 소수점 2째자리까지 나타내주기 위해 round()를 추가해줍니다.

 

이제 위 테이블을 피벗테이블로 나타내 주면

sns.heatmap(data="필요한 데이터 입력하기",
           annot=True, #각 cell의 데이터 표기 유무를 나타냅니다!
           fmt='.2%', #values(데이터의 값) 값의 소수점 표기
           vmin=0,#최소값 설정
           vmax=1,#최댓값 설정
           cmap="BuGn" #히트맵의 색을 설정합니다
            )

"필요한 데이터"에 retention을 입력해줍니다.

 

 

 

이렇게 최종결과를 얻어낼 수 있습니다.

 


결론

완주율은 전체적으로 떨어지는 것을 볼 수 있습니다.

다른요인으로 완주율이 떨어졌다고 보는것이 맞을 수 있습니다.

 

개인적인생각: 유의성 검정을 했으면 더 좋을 것 같습니다.