파이썬 분석 실무, 유저 Funnel 분석 - (6) EDA, 일별 주요 통계

|

python 분석 실무, 유저 funnel 분석 따라 공부하기

  1. 데이터 불러오기
  2. 날짜 데이터 다루기
  3. 결측치 처리
  4. 예측 모델을 통한 결측치 처리
  5. 데이터 전처리
  6. EDA, 일별 주요 통계

EDA(탐색적 데이터 분석, Exploratory Data Analysis)

데이터 전처리를 마쳤다면, 데이터를 둘러보며 어떤 것이 의미있는 정보인지 확인해야 한다. 기본적으로 날짜데이터가 있는 경우는 날짜의 연도/월/일/요일 등 어떤 타입의 날짜 데이터와 연관성이 있는지 알아본다. 유저의 로그를 가지고 분석하는 경우 특정 행동끼리의 상관성도 살펴볼 수 있다.

여기에서는 아래와 같이 EDA를 진행한다.

  • 일별 주요 통계 <- 이 글에서는 여기
  • 변수별 특성
  • 구간별 전환율(Funnel Analysis)
  • 클러스터링
  • 클러스터별 전환율 차이 파악

기본 트렌드 체크

  • 일별 로그 카운트 : 일별로 해당 액션이 일어난 수
  • 일별 세션 카운트 : 일별로 해당 액션을 한 유닉크 유저수
  • 요일별 세션 카운트 : 요일별로 해당 액션을 한 유니크 유저수 트렌드
# daily log size

df.groupby('datetime').size().plot(c='r');

plt.title("Daily Log Count")
plt.grid(color='lightgrey', alpha=0.5, linestyle='--')
plt.tight_layout()

일별 로그 카운트

# daily session counts => Active index

df.groupby('datetime')['sessionid'].nunique().plot(c='b');

plt.title("Daily Log Count")
plt.grid(color='lightgrey', alpha=0.5, linestyle='--')
plt.tight_layout()

일별 세션 카운트

## daily session count (weekofday)
# 0: Monday, 6: Sunday

s = df.groupby("datetime")['sessionid'].nunique()
s.index = s.index.dayofweek # datetime 요일로 변환

s.plot(color='grey', kind='bar', rot=0);

plt.title("Daily Session")
plt.grid(color='lightgrey', alpha=0.5, linestyle='--')
plt.tight_layout()

요일별 세션 카운트 0: Monday, 6: Sunday

Note.

  • 앱 로그에 sessionality 존재
  • 로그 수와 세션수 트렌드가 유사
  • 주말에 사용성이 매우 감소하고 주중 초반이 높은 편
  • 문서앱이라는 특성상, 직장인 혹은 학생이 주로 사용할 것으로 가정하면 당연한 결과

해당 서비스에 맞는 일별 트렌드 확인

  • 일별, 확장자별 로그수
  • 일별, 위치별 로그수
  • 일별, 액션별 로그수
  • 일별, 화면 스크린별 유니크 유저수
# daily trend by extention
df.groupby(['datetime', 'ext']).size().unstack().dropna(axis=1).plot(figsize=(12,7));

plt.title("Daily Extention Trend")
plt.grid(color = 'lightgrey', alpha=0.5, linestyle='--') # alpha는 투명도
plt.tight_layout()

일별 확장자별 로그수

# daily trend by doc position
df.groupby(['datetime', 'documentposition']).size().unstack().dropna(axis=1).plot(figsize=(12, 7));

plt.title("Daily documentposition")
plt.grid(color='lightgrey', alpha=0.5, linestyle='--')
plt.tight_layout()

일별 위치별 로그수

# daily trend by action type
df.groupby(['datetime', 'actiontype']).size().unstack().dropna(axis=1).plot(figsize=(12, 7));

plt.title("Daily documentposition")
plt.grid(color='lightgrey', alpha=0.5, linestyle='--')
plt.tight_layout()

일별 액션별 로그수

# daily trend by screen name
df.groupby(['datetime', 'screen']).size().unstack().dropna(axis=1).plot(figsize=(12, 7));

plt.title("Daily documentposition")
plt.grid(color='lightgrey', alpha=0.5, linestyle='--')
plt.tight_layout()

일별 스크린별 유니크 유저수

#heat map
screens = df.groupby(['datetime', 'screen'])['sessionid'].nunique().unstack().fillna(0).astype(int)
# cols order change
screens = screens[screens.mean().sort_values(ascending=False).index]

plt.subplots(figsize=(17,8))

sns.heatmap(screens, annot=True, fmt='d', annot_kws={'size':12}, cmap='Blues');

plt.title("screen count daily")
plt.tight_layout()

일별 스크린별 유니크 유저수 히트맵

Note.

  • doc, pdf, xls 순으로 주로 사용
  • 주요 문서 이용 위치는 otherapp
  • Main -> 구매완료(purchase_done) 까지 과정에서 대부분 이탈

이 글에서 사용한 Pandas 함수 정리

groupby()

특정 항목을 기준으로 갯수, 평균 등의 수치를 보고 싶을 때, 유용한 함수이다. 여기에서는 날짜별 로그수, 세션수 등을 봤다. plot()과 함께 쓰면, 따로 해당 데이터를 값으로 저장하지 않고 바로 경향성을 그래프로 확인할 수 있다.

  • .groupby([col1, col2]).apply() : 앞에 있는 칼럼으로 먼저 묶인다.
  • .groupby([col1, col2])['col3'].apply() : 구분은 col1, col2이지만, 값은 col3에 대한 걸 보고 싶을 때
  • apply 부분에 사용할 수 있는 함수들
    • df.groupby('A').sum()
      • 해당 내용 항목별로 카테고리 묶음,숫자데이터 다른 칼럼 값끼리 더함
    • df.groupby('A').size()
      • 해당 내용 항목별로 카테고리 묶음, 그 사이즈 확인
      • Series의 .value_counts()와 비슷
    • df.groupby('A')['B'].nunique()
      • ‘A’ 내용 항목별로 카테고리 묶고, 거기의 ‘B’ 유니크한 값 숫자 확인
    • df.groupby.reset_index(): 구분으로 사용한 칼럼값을 index로 쓰고 싶지 않을때, 구분으로 묶은 것을 값으로 넣어서 출력함

        df.groupby(['datetime', 'ext']).size().reset_index().head()
      
        # datetime	ext	0
        # 0	2016-07-01	DOC	3298
        # 1	2016-07-01	HWP	908
        # 2	2016-07-01	PDF	3177
        # 3	2016-07-01	PPT	918
        # 4	2016-07-01	SHEET	2
      
    • df.groupby.unstack(level=0): povot, stack, groupby 함수에 의해 기준칼럼이 값별로 row에 있는 것을 col로 옮겨서 출력해줌
      • Q. prefix, sufix 넣는 방법은 없나..?
        df.groupby(['datetime', 'screen'])['sessionid'].nunique().unstack().head()
      
        # screen	InProduct_Mob	InProduct_Web	Main	Per_Dir	Pub_Dir	Purchase_done	Purchase_page
        # datetime							
        # 2016-07-01	143.0	178.0	3911.0	381.0	1112.0	2.0	24.0
        # 2016-07-02	92.0	140.0	2935.0	251.0	888.0	2.0	15.0
        # 2016-07-03	50.0	85.0	2005.0	197.0	648.0	NaN	33.0
        # 2016-07-04	124.0	120.0	3016.0	349.0	847.0	NaN	32.0
        # 2016-07-05	127.0	159.0	3631.0	354.0	942.0	1.0	28.0
      

plot()

pandas.DataFrame.plot에서 이번에 썼던 것만 봐보자.

  • .gird()
  • .title()
  • tight_layout()
  • X(index),Y(column)으로 plotting
# groupby 이후에 unstack() 사용한 이유, X,Y 잡아주기

df.groupby(['datetime', 'ext']).size().unstack().dropna(axis=1).plot(figsize=(12,7));

sns.heatmap()

seaborn.heatmap를 한번 봐보자.

  • parameters
    • annot : bool or rectangular dataset, optional

      If True, write the data value in each cell. If an array-like with the same shape as data, then use this to annotate the heatmap instead of the raw data.

    • fmt : string, optional
        sns.heatmap(screens, annot=True, fmt='d', annot_kws={'size':12}, cmap='Blues');
      

      String formatting code to use when adding annotations.

    • annot_kws : dict of key, value mappings, optional, 값 텍스트 부분 설정

      Keyword arguments for ax.text when annot is True.

Numbers formatting with format() 1

포맷 코드로 숫자와 글 이용하기

  • For positional arguments(순서 위치로 포맷 이용)

  • For keyword arguments(값을 지정해 포맷 이용)

Numbers formatting with

Type Meaning
d Decimal integer
c Corresponding Unicode character
b Binary format
o Octal format
x Hexadecimal format (lower case)
X Hexadecimal format (upper case)
n Same as ‘d’. Except it uses current locale setting for number separator
e Exponential notation. (lowercase e)
E Exponential notation (uppercase E)
f Displays fixed point number (Default: 6)
F Same as ‘f’. Except displays ‘inf’ as ‘INF’ and ‘nan’ as ‘NAN’
g General format. Rounds number to p significant digits. (Default precision: 6)
G Same as ‘g’. Except switches to ‘E’ if the number is large.
% Percentage. Multiples by 100 and puts % at the end.

실습 파일 확인하기