In [1]:
import numpy as np
import pandas as pd

import matplotlib
import matplotlib.pyplot as plt

%matplotlib inline

In [2]:
!ls ../_dataset/clickstream/


Data1_Profiles.xlsx  Data2_Clickstreams.tab  Data2_Clickstreams.tsv

In [3]:
df = pd.read_csv(
    "../_dataset/clickstream/Data2_Clickstreams.tab",
    delimiter="\t",
    encoding="ms949",
)

In [4]:
df.head()


Out[4]:
CUS_ID TIME_ID SITE SITE_CNT ST_TIME SITE_NM BACT_NM MACT_NM ACT_NM
0 1 2012070905 search.naver.com 3.0 794.0 네이버 검색 인터넷/컴퓨터 검색 포털검색
1 1 2012072507 plus.google.com 1.0 1.0 구글 Plus 커뮤니티 블로그/SNS SNS
2 1 2012081116 joongang.joinsmsn.com 2.0 5.0 중앙일보 뉴스/미디어 일간지 종합일간지
3 1 2012090304 news.naver.com 5.0 504.0 네이버 뉴스 뉴스/미디어 인터넷신문 포털뉴스
4 1 2012090506 news.nate.com 1.0 0.0 네이트 뉴스 뉴스/미디어 인터넷신문 포털뉴스

In [5]:
profile_df = pd.read_excel("../_dataset/clickstream/Data1_Profiles.xlsx")
profile_df.head()


Out[5]:
CUS_ID GENDER AGE JOB RESIDENCE
0 1 남자 47 무직/기타 충청
1 10 남자 36 영업/마케팅 서울
2 100 남자 44 사무관리직 경기
3 1000 여자 45 영업/마케팅 서울
4 1001 남자 50 사무관리직 경상

In [6]:
merged_df = pd.merge(
    df,
    profile_df,
    on="CUS_ID",
)

In [7]:
merged_df.head()


Out[7]:
CUS_ID TIME_ID SITE SITE_CNT ST_TIME SITE_NM BACT_NM MACT_NM ACT_NM GENDER AGE JOB RESIDENCE
0 1 2012070905 search.naver.com 3.0 794.0 네이버 검색 인터넷/컴퓨터 검색 포털검색 남자 47 무직/기타 충청
1 1 2012072507 plus.google.com 1.0 1.0 구글 Plus 커뮤니티 블로그/SNS SNS 남자 47 무직/기타 충청
2 1 2012081116 joongang.joinsmsn.com 2.0 5.0 중앙일보 뉴스/미디어 일간지 종합일간지 남자 47 무직/기타 충청
3 1 2012090304 news.naver.com 5.0 504.0 네이버 뉴스 뉴스/미디어 인터넷신문 포털뉴스 남자 47 무직/기타 충청
4 1 2012090506 news.nate.com 1.0 0.0 네이트 뉴스 뉴스/미디어 인터넷신문 포털뉴스 남자 47 무직/기타 충청

각 이용자별로 다음의 정보를 구하시오.

  • DWELLTIME ( 체류시간 ) - ST_TIME 의 총합
  • PAGEVIEWS ( 페이지뷰 ) - SITE_CNT 의 총합

In [8]:
cus_df = merged_df.groupby("CUS_ID").get_group(1)
# cus_df.sort_values("TIME_ID")

In [9]:
merged_df.groupby("CUS_ID").agg(
    {
        "ST_TIME": {"체류시간": "sum"},
        "SITE_CNT": {"페이지뷰": "sum"},
        "SITE_NM": {"방문한 사이트 수": lambda x: np.unique(x).size},    # 접속한 서로 다른 사이트 수
        "BACT_NM": {"커버리지": lambda x: x.unique().size / 22},
        "TIME_ID": {"총 접속 일수": lambda x: x.apply(lambda y: str(y)[:8]).unique().size}
    }
)


Out[9]:
BACT_NM ST_TIME SITE_NM TIME_ID SITE_CNT
커버리지 체류시간 방문한 사이트 수 총 접속 일수 페이지뷰
CUS_ID
1 0.727273 357978.0 201 205 13656.0
2 0.909091 836048.0 573 105 25498.0
3 0.772727 388378.0 270 105 10413.0
4 0.772727 275572.0 166 107 12831.0
5 0.909091 501922.0 328 151 13267.0
6 0.636364 56543.0 85 79 1972.0
7 0.772727 573113.0 228 243 20063.0
8 0.636364 101640.0 316 173 5871.0
9 0.863636 535910.0 438 255 22054.0
10 0.772727 1222047.0 236 116 43544.0
11 0.772727 90562.0 450 123 5582.0
12 0.636364 68144.0 68 113 4376.0
13 0.545455 426988.0 129 153 10672.0
14 0.863636 644274.0 218 100 21572.0
15 0.772727 595743.0 330 174 25967.0
16 0.772727 90895.0 159 100 3532.0
17 0.727273 172435.0 175 101 7284.0
18 0.818182 518476.0 250 201 11597.0
19 0.863636 329314.0 260 101 12087.0
20 0.909091 125222.0 247 123 7163.0
21 0.590909 102183.0 83 119 3400.0
22 0.818182 302502.0 241 111 12772.0
23 0.772727 489285.0 793 119 23935.0
24 0.818182 421206.0 197 130 12917.0
25 0.863636 385731.0 345 206 36266.0
26 0.772727 530405.0 316 111 16921.0
27 0.863636 546656.0 428 139 21490.0
28 1.000000 592353.0 580 127 23327.0
29 0.772727 110400.0 201 100 4760.0
30 0.818182 689042.0 286 112 17056.0
... ... ... ... ... ...
2471 0.727273 283823.0 342 210 16856.0
2472 0.636364 105872.0 233 128 6666.0
2473 0.863636 403049.0 298 108 23242.0
2474 0.727273 333821.0 136 112 11948.0
2475 0.818182 213784.0 298 99 13124.0
2476 0.909091 357839.0 317 184 21681.0
2477 0.818182 290642.0 196 106 15034.0
2478 0.681818 334479.0 111 140 12850.0
2479 0.727273 315632.0 176 170 9149.0
2480 0.909091 465506.0 361 165 16175.0
2481 0.727273 279963.0 167 141 11984.0
2482 0.727273 213237.0 190 123 7376.0
2483 0.909091 1062526.0 475 245 56254.0
2484 0.909091 429821.0 307 198 22134.0
2485 0.772727 386116.0 503 182 25447.0
2486 0.727273 180471.0 177 148 15399.0
2487 0.909091 1319476.0 401 207 63960.0
2488 0.727273 150604.0 271 108 6529.0
2489 0.772727 201488.0 208 100 7536.0
2490 0.863636 364855.0 222 182 21261.0
2491 0.863636 854226.0 343 266 49754.0
2492 0.545455 53331.0 52 115 2520.0
2493 0.681818 177696.0 199 111 7635.0
2494 0.863636 409188.0 370 131 20479.0
2495 0.909091 925589.0 346 163 40101.0
2496 0.909091 487187.0 170 113 10349.0
2497 0.818182 146626.0 270 138 8419.0
2498 0.863636 606710.0 431 171 24179.0
2499 0.863636 403725.0 227 114 12541.0
2500 0.954545 828670.0 492 179 25823.0

2500 rows × 5 columns


In [10]:
# 성별에 따른 카테고리 접속 비중

merged_df.groupby(["GENDER", "BACT_NM"]).size().unstack()


Out[10]:
BACT_NM 건강/의학 게임 교육/학원 금융/부동산 뉴스/미디어 문학/예술 비즈니스/경제 사회/문화/종교 생활/가정/취미 서비스 ... 엔터테인먼트 여행 온라인교육 유통/판매/운송 인터넷/컴퓨터 정보통신/IT 정치/행정 제조 커뮤니티 학문
GENDER
남자 9967 86938 16550 203431 870501 2533 53346 8083 21583 26066 ... 135974 19767 33549 16684 2561413 31523 49391 13540 574689 1462
여자 7111 33028 11937 100214 377095 1508 30655 4237 14636 18938 ... 63166 15448 24036 10869 1469102 21061 28132 9010 363187 812

2 rows × 22 columns


In [11]:
# 일단은 하나의 그룹에 대해서 연산을 수행하자

male_group = merged_df.groupby("GENDER").get_group("남자")
male_group.BACT_NM.value_counts().sort_values(ascending=False)[:3]


Out[11]:
인터넷/컴퓨터    2561413
뉴스/미디어      870501
쇼핑          588936
Name: BACT_NM, dtype: int64

In [12]:
# 각 그룹별 방문 횟수가 많은 사이트 카테고리 Top 5개

merged_df\
    .groupby("GENDER")\
    .apply(
        lambda x: x.BACT_NM.value_counts().sort_values(ascending=False)[:5]
    )


Out[12]:
GENDER         
남자      인터넷/컴퓨터    2561413
        뉴스/미디어      870501
        쇼핑          588936
        커뮤니티        574689
        금융/부동산      203431
여자      인터넷/컴퓨터    1469102
        쇼핑          495790
        뉴스/미디어      377095
        커뮤니티        363187
        금융/부동산      100214
Name: BACT_NM, dtype: int64

In [13]:
merged_df.BACT_NM.unique().size


Out[13]:
22