'범주형 데이터의 연관규칙 분석'에 해당되는 글 1건

  1. 2016.05.25 [R 연관규칙 (Association Rule)] 범주형 및 연속형 데이터의 연관규칙 분석 (12)

지난번 포스팅에서는 거래 데이터 (transaction data)를 가지고 R을 사용하여 연관규칙 분석을 하였습니다.

 

이번 포스팅에서는 범주형 데이터와 연속형 데이터를 가지고 연관규칙을 생성(association rule mining on categorical data and continuous data)하는 방법을 소개하겠습니다. 

 

보통 연관규칙 분석을 배운다고 하면 거래 데이터(transaction data)만 가능한걸로 알고 끝내기 쉬운데요, 범주형 또는 연속형 데이터에 대해서도 연관규칙을 생성할 수 있다는 것을 알고 나면 연관규칙을 적용할 수 있는 범위가 늘어납니다.

 

가령 범주형 데이터를 가지고 연관규칙을 찾는 다면 아래와 같은 예가 있을 수 있습니다. 연속형 데이터를 범주형 데이터로 변환 (이산형화, discretization)하면 위의 예와 같은 연관규칙을 도출할 수 있습니다. 아래 예에서는 '연령'을 '연령대'로 구간을 나누었습니다.

 

 

 

[범주형 데이터 연관규칙 예]

 

{선형대수 수강 = Pass, 통계/확률 수강 = Pass}  →  {Machine Learning 수강 = Pass}

 

{성별 = 여성, 거주지역 = 분당, 연령대 = 30세~39세, 아동용품 구매경험 여부 = Yes}  →  {모바일쇼핑재구매 = Yes} 

 

 

범주형 데이터 또는 연속형 데이터를 가지고 연관규칙 분석을 하는 기본 원리는 "이항 데이터(binary data)로 변환하여 연관규칙 분석 방법을 수행"하는 것입니다.

 

아래의 가상의 데이터셋을 가지고 예를 들어보겠습니다.

성별(Gender), 아동상품구매여부(Child_Prd_YN), 모바일앱이용여부(Mobile_App_Use), 재구매여부(Re_Order) 등의 변수는 범주형 데이터(categorical data)이며, 연령(Age)은 연속형 데이터(continuous data)에 속합니다.  이를 '1', '0' 의 두개의 값만 가지는 변수로 변환하는 이항변수화(Binarization)을 하면 아래와 같습니다.

 

 

[ 범주형/연속형 데이터의 이항변수화 (Binarization) ]

 

 

 

이항변수화를 할 때 구간을 몇 개로 나눌 것인지가 중요한데요, 너무 잘게 쪼개서 구간을 많이 만들게 되면 연관규칙이 잘 안나올 수 있습니다. 왜냐하면 구간을 잘게 쪼개면 각 구간별 freqnency 가 작아져서 지지도(support) 값이 낮아지고, inqrequent item set은 pruning 되기 때문입니다.  따라서 적당한(?) 구간으로 (너무 잘게 쪼개지 않게) 나누는 것이 필요합니다.  위의 예에서는 연령(age)의 경우 20대, 30대, 40대의 3개 구간으로만 나누어보았습니다.

 

 

R을 가지고 위의 가상의 간략한 예제 데이터를 가지고 연관규칙을 생성해보겠습니다.

 

R의 as(dataset, "transactions") 함수를 이용하면 연관규칙분석을 위한 이항변수화(binirization) 작업을 별도로 안해줘도 되므로 편리합니다. 단, 연속형 변수를 범주형 변수로 만드는 이산형화(discretization)하는 작업은 아래 예처럼 코딩을 해줘야 합니다.

 

 

(1) 범주형 dataset 확보, 연속형 변수의 이산형화(discretization)

 

> ##--------------------------------------------------------------
> ## categorical data -> binarization -> association rule analysis
> ##--------------------------------------------------------------
> 
> # vector -> cbind -> data.frame
> cust_id <- c(1, 2, 3, 4, 5, 6)
> gender <- c("FEMALE", "MALE", "FEMALE", "FEMALE", "MALE", "FEMALE")
> age <- c(23, 28, 42, 34, 45, 36)
> child_prd_yn <- c("NO", "NO", "NO", "YES", "NO", "YES")
> mobile_app_use <- c("YES", "YES", "NO", "YES", "NO", "YES")
> re_order <- c("YES", "NO", "NO", "YES", "NO", "YES")
> 
> cust_mart <- cbind(cust_id, gender, age, child_prd_yn, mobile_app_use, re_order)
> cust_mart <- as.data.frame(cust_mart)
> sapply(cust_mart, class)
       cust_id         gender            age   child_prd_yn mobile_app_use       re_order 
      "factor"       "factor"       "factor"       "factor"       "factor"       "factor" 
> 
> 
> # cust_id : factor -> character
> # age : factor -> numeric
> cust_mart <- transform(cust_mart, 
+                        cust_id = as.character(cust_id),
+                        age = as.numeric(age))
> 
> sapply(cust_mart, class)
       cust_id         gender            age   child_prd_yn mobile_app_use       re_order 
   "character"       "factor"      "numeric"       "factor"       "factor"       "factor" 
> 
> 
> # age : custinuous data -> discretization
> cust_mart <- within(cust_mart, {
+   age_cd = character(0)
+   age_cd[ age <= 29 ] = "age_20"
+   age_cd[ age > 29 & age <= 39 ] = "age_30"
+   age_cd[ age > 39 ] = "age_40"
+   age_cd = factor(age_cd, level = c("age_20", "age_30", "age_40"))
+ })
> 
> 
> # dataset for assocition rule : (1) deleting 'cust_id', 'age'
> cust_mart_ar <- subset(cust_mart, select = -c(cust_id, age))
> str(cust_mart_ar)
'data.frame':	6 obs. of  5 variables:
 $ gender        : Factor w/ 2 levels "FEMALE","MALE": 1 2 1 1 2 1
 $ child_prd_yn  : Factor w/ 2 levels "NO","YES": 1 1 1 2 1 2
 $ mobile_app_use: Factor w/ 2 levels "NO","YES": 2 2 1 2 1 2
 $ re_order      : Factor w/ 2 levels "NO","YES": 2 1 1 2 1 2
 $ age_cd        : Factor w/ 3 levels "age_20","age_30",..: 1 1 1 1 1 1
> 

 

 

 

(2) 거래데이터 형식으로 데이터 변환하기 : as(dataset, "transactions")

 

> # dataset for assocition rule : (2) transaction data format
> install.packages("arules")
Installing package into ‘C:/Users/Owner/Documents/R/win-library/3.2’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/bin/windows/contrib/3.2/arules_1.4-1.zip'
Content type 'application/zip' length 1885277 bytes (1.8 MB)
downloaded 1.8 MB

package ‘arules’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
	C:\Users\Owner\AppData\Local\Temp\Rtmp0ybsUO\downloaded_packages
> library(arules)
필요한 패키지를 로딩중입니다: Matrix

다음의 패키지를 부착합니다: ‘arules’

The following objects are masked from ‘package:base’:

    abbreviate, write

Warning message:
패키지 ‘arules’는 R 버전 3.2.5에서 작성되었습니다 
> 
> cust_mart_ar_tr <- as(cust_mart_ar, "transactions")
> str(cust_mart_ar_tr)
Formal class 'transactions' [package "arules"] with 3 slots
  ..@ data       :Formal class 'ngCMatrix' [package "Matrix"] with 5 slots
  .. .. ..@ i       : int [1:30] 0 2 5 7 8 1 2 5 6 8 ...
  .. .. ..@ p       : int [1:7] 0 5 10 15 20 25 30
  .. .. ..@ Dim     : int [1:2] 11 6
  .. .. ..@ Dimnames:List of 2
  .. .. .. ..$ : NULL
  .. .. .. ..$ : NULL
  .. .. ..@ factors : list()
  ..@ itemInfo   :'data.frame':	11 obs. of  3 variables:
  .. ..$ labels   : chr [1:11] "gender=FEMALE" "gender=MALE" "child_prd_yn=NO" "child_prd_yn=YES" ...
  .. ..$ variables: Factor w/ 5 levels "age_cd","child_prd_yn",..: 3 3 2 2 4 4 5 5 1 1 ...
  .. ..$ levels   : Factor w/ 7 levels "age_20","age_30",..: 4 5 6 7 6 7 6 7 1 2 ...
  ..@ itemsetInfo:'data.frame':	6 obs. of  1 variable:
  .. ..$ transactionID: chr [1:6] "1" "2" "3" "4" ...
> 

 

 

 

 

(3) 연관규칙 생성 (association rule generation) : arules package, apriori algorithm

 

 

> # association rule generation
> cust_mart_ar_tr_rule <- apriori(cust_mart_ar_tr, 
+                              parameter = list(support = 0.3, confidence = 0.5))
Apriori

Parameter specification:
 confidence minval smax arem  aval originalSupport support minlen maxlen target   ext
        0.5    0.1    1 none FALSE            TRUE     0.3      1     10  rules FALSE

Algorithmic control:
 filter tree heap memopt load sort verbose
    0.1 TRUE TRUE  FALSE TRUE    2    TRUE

Absolute minimum support count: 1 

Warning in apriori(cust_mart_ar_tr, parameter = list(support = 0.3, confidence = 0.5)) :
  You chose a very low absolute support count of 1. You might run out of memory! Increase minimum support.

set item appearances ...[0 item(s)] done [0.00s].
set transactions ...[9 item(s), 6 transaction(s)] done [0.00s].
sorting and recoding items ... [9 item(s)] done [0.00s].
creating transaction tree ... done [0.00s].
checking subsets of size 1 2 3 4 5 done [0.00s].
writing ... [135 rule(s)] done [0.00s].
creating S4 object  ... done [0.00s].

 

 

(4) 연관규칙 탐색 (inspection of association rule) : inspect(association rule)

 

 

> # association rule inspection > inspect(head(cust_mart_ar_tr_rule, 20)) # head 20 rules lhs rhs support confidence lift 1 {} => {re_order=YES} 0.5000000 0.5000000 1.0 2 {} => {re_order=NO} 0.5000000 0.5000000 1.0 3 {} => {child_prd_yn=NO} 0.6666667 0.6666667 1.0 4 {} => {mobile_app_use=YES} 0.6666667 0.6666667 1.0 5 {} => {gender=FEMALE} 0.6666667 0.6666667 1.0 6 {} => {age_cd=age_20} 1.0000000 1.0000000 1.0 7 {gender=MALE} => {re_order=NO} 0.3333333 1.0000000 2.0 8 {re_order=NO} => {gender=MALE} 0.3333333 0.6666667 2.0 9 {gender=MALE} => {child_prd_yn=NO} 0.3333333 1.0000000 1.5 10 {child_prd_yn=NO} => {gender=MALE} 0.3333333 0.5000000 1.5 11 {gender=MALE} => {age_cd=age_20} 0.3333333 1.0000000 1.0 12 {mobile_app_use=NO} => {re_order=NO} 0.3333333 1.0000000 2.0 13 {re_order=NO} => {mobile_app_use=NO} 0.3333333 0.6666667 2.0 14 {mobile_app_use=NO} => {child_prd_yn=NO} 0.3333333 1.0000000 1.5 15 {child_prd_yn=NO} => {mobile_app_use=NO} 0.3333333 0.5000000 1.5 16 {mobile_app_use=NO} => {age_cd=age_20} 0.3333333 1.0000000 1.0 17 {child_prd_yn=YES} => {re_order=YES} 0.3333333 1.0000000 2.0 18 {re_order=YES} => {child_prd_yn=YES} 0.3333333 0.6666667 2.0 19 {child_prd_yn=YES} => {mobile_app_use=YES} 0.3333333 1.0000000 1.5 20 {mobile_app_use=YES} => {child_prd_yn=YES} 0.3333333 0.5000000 1.5

 

 

 

(5) 특정 관심있는 연관규칙만 선별해서 보기 : subset()

 

  예) 연관규칙의 right-hand side 에 "재구매여부=예"를 포함하고 "lift >=2" 인 rule만 선별(subset)

 

> # subset : right-hand sied in "re_order = YES" & lift >= 2 > cust_mart_ar_tr_rule_reorder <- subset(cust_mart_ar_tr_rule, + subset = rhs %in% "re_order=YES" & lift >= 2) > > inspect(cust_mart_ar_tr_rule_reorder) lhs rhs support confidence lift 1 {child_prd_yn=YES} => {re_order=YES} 0.3333333 1 2 2 {child_prd_yn=YES, mobile_app_use=YES} => {re_order=YES} 0.3333333 1 2 3 {gender=FEMALE, child_prd_yn=YES} => {re_order=YES} 0.3333333 1 2 4 {child_prd_yn=YES, age_cd=age_20} => {re_order=YES} 0.3333333 1 2 5 {gender=FEMALE, mobile_app_use=YES} => {re_order=YES} 0.5000000 1 2 6 {gender=FEMALE, child_prd_yn=YES, mobile_app_use=YES} => {re_order=YES} 0.3333333 1 2 7 {child_prd_yn=YES, mobile_app_use=YES, age_cd=age_20} => {re_order=YES} 0.3333333 1 2 8 {gender=FEMALE, child_prd_yn=YES, age_cd=age_20} => {re_order=YES} 0.3333333 1 2 9 {gender=FEMALE, mobile_app_use=YES, age_cd=age_20} => {re_order=YES} 0.5000000 1 2 10 {gender=FEMALE, child_prd_yn=YES, mobile_app_use=YES, age_cd=age_20} => {re_order=YES} 0.3333333 1 2

 

 

 

제일 마지막 결과까지 보고 나면 '어, 저거 rule-base 규칙인데...어디서 많이 본건데...' 싶지 않으신가요?  Decision Tree랑 뭔가 모르게 비슷하다는 생각이 좀 들지요?  혹시 명확한 target을 가진 (설명력이 좋은) 분류 규칙 찾는 목적이라면 Decision Tree 를 쓰는게 더 효과적일 수 있습니다.  (가령, 재구매고객의 특성이 뭐지? 처럼요)

 

그런데 뭔지는 지금은 모르겠지만 '기존에는 잘 몰랐으면서 & insight가 담겨있고 & 설명가능하고 & 실행가능한' 연관규칙을 한번 찾아봐 줘, 그러면 내가 그 rule들을 평가해보고 쓸만한거 추려서 이용해볼게...하는 상황이면 연관규칙 분석을 사용하시면 됩니다. 

 

Decision Tree는 하햐식 방식(Top to bottom)으로 분류규칙을 만들어나가는데 반해 (즉, child node는 parent node에 종속적), 연관규칙, 순차패턴은 규칙이 서로 독립적이라는게 다릅니다.

 

이상으로 범주형, 연속형 데이터의 연관규칙 분석에 대해서 알아보았습니다.

 

다음번 포스팅에서는 순차분석(sequence analysis)에 대해서 알아보겠습니다.

 

이번 포스팅이 도움이 되었다면 아래의 '공감 ~♡'를 꾸욱~ 눌러주세요.

 

Posted by R Friend R_Friend

댓글을 달아 주세요

  1. Ashtray Kim 2016.09.30 10:13  댓글주소  수정/삭제  댓글쓰기

    글 잘읽었습니다~ 즉, binary 셋을 sparse format으로 변환시킨걸 arules로 분석을 하면 된다는 것이죠?
    저번에 질문드려서 글까지 작성해주신 텍스트 쪼개서 세로로 배열하는 문제(감사합니다!) 에도 AR을 적용해볼 수 있을까요?
    키워드가 엄청 많은데.. 이걸 binary로 변환시키는게 가능한 작업인지 ㅋㅋ

    • R Friend R_Friend 2016.09.30 14:55 신고  댓글주소  수정/삭제

      지난번 문의주셨던 포맷이면 read.transactions("dataset.csv") 함수를 사용해서 불러온후 arules package 바로 사용하시면 됩니다

    • Ashtray Kim 2016.09.30 15:59  댓글주소  수정/삭제

      쪼개기 전 데이터셋 말씀하시는건가요? 한 열을 transaction으로 볼 수 있기는 한데..
      그 쪼개기 전이라면 분석이 불가능한 포맷같아보여서요.
      키워드별로 다 쪼개고, transaction별 item matrix? 형태로 만들어줘야 하지 않나요?

  2. Ashtray Kim 2016.09.30 16:17  댓글주소  수정/삭제  댓글쓰기

    원 데이터 형태는

    id Keyword_Count
    203941948 연관:3^티스토리:4^컴퓨터:6
    203283192 바보:3^모니터:4^쥬스:6

    이런 형태입니다.

    • R Friend R_Friend 2016.09.30 16:23 신고  댓글주소  수정/삭제

      이런 형태 쪼갠 후에, 세로로 세우고, reshape oackage의 melt(), cast() 함수써서 재구조화해서 item별로 dummy 변수로 만들어줘야겠네요

    • Ashtray Kim 2016.09.30 17:45  댓글주소  수정/삭제

      음 좀 해봤는데요.. 아무래도 transaction 타입으로 불러오려면
      item matrix여야 하는 것 같습니다.
      약 7000*10000 크기의 matrix로 변환시켜야 하는데.. 또하나의 고비네요 ㅎㅎ

    • R Friend R_Friend 2016.09.30 18:26 신고  댓글주소  수정/삭제

      sqldf 로 항목별 빈도 구한 다음에, 일차로
      비빈발 항목(infrequent item)은 사전에 가지치기(pruning) 하시면 칼럼 숫자가 줄텐데요.

    • Ashtray Kim 2016.10.01 13:54  댓글주소  수정/삭제

      조언 감사합니다. 재구조화같은 경우, 조언해주시는 부분과 다른 방법 여러가지로 생각해보겠습니다.

      그리고, 궁금한 점이 있다면, arules 패키지가 apriori알고리즘을 사용하는지 여부입니다. apriori 알고리즘(이해하다 말았지만..ㅠㅠ)에서 비빈발 항목집합을 pruning하는 부분이 있는 걸로 알고있는데요. 사람이 직접 사전 pruning을 해줘야 할 필요가 있는지와, 해야한다면 그 기준(하위 몇퍼센트를 제외한다든지, 몇번만 출현한건 제외한다든지..)은 어떻게 정해야 하는지 궁금합니다.
      (이런 종류의 결정을 할 때, 기준이 되는 수치가 항상 어려운 것 같습니다. 정해진 것이 있는지, 경험에 따라 임의로 정하면 되는 것인지요..)

    • Ashtray Kim 2016.10.01 14:59  댓글주소  수정/삭제

      더 찾아봤는데요. read.transaction으로 불러올 수 있는 데이터가 2종류가 있네요

      1) format="basket"으로 읽어올 수 있는 데이터는 한 행이 203941948 연관,티스토리,컴퓨터 형태로,
      한 transaction에 구입한 모든 항목이 1개의 행에 다 들어간 것.

      2) format="single"로 읽어올 수 있는 데이터는 한 행에 하나의 item만 들어갈 수 있는 형태. 즉,
      203941948 연관
      203941948 티스토리
      203941948 컴퓨터

      인 것 같습니다. 실제 제 원본 데이터에 적용이 되는지는 화요일에 적용해봐야 알 것 같네요.

    • R Friend R_Friend 2016.10.01 16:07 신고  댓글주소  수정/삭제

      데이터를 구분자 가준으로 분리한 후에 세로로 세워서, format="single"로 데이터 불러온후에 arules 로 분석하면 되겠네요. min support 지정하시면 알아서 비빈발 항목 pruning 해줍니다.

      format="single"이 되는지 처음 알았네요. 좋은 정보 감사합니다.

  3. OriR 2017.02.16 13:52 신고  댓글주소  수정/삭제  댓글쓰기

    좋은 글 잘 읽었습니다.^^ 질문이 있는데, 마지막에 cust_mart_ar_tr_rule_reorder 를 plot으로 그려봤을 때, rules은 13개지만 커다란 원 하나만 그려지더라구요
    그리고 lhs 에 +x items 라는 말이 나오는데 그게 정확히 어떤 걸 말하는지 이해가 잘 안됩니다. ㅠ
    어떤 의미로 해석해야 할까요??

    • R Friend R_Friend 2017.03.15 23:45 신고  댓글주소  수정/삭제

      포스팅 본문의 예시는 알고리즘 설명을 위해서 아주 간단하게 극소수의 transaction 을 가짜 예시로 만든거다 보니 rule이 나오긴 했지만 rule 간 차이가 별로 없습니다.

      제대로 된 데이터셋으로 rule을 한번 만들어 보시구요, 그래프 그릴 때 아래 포스팅 참고해보시지요.
      http://rfriend.tistory.com/221

      arulesViz package 로 연관규칙 네트워크 그래프를 그려보면 동그라미만 뎅그러니 있고 화살표가 그려지다 말더라구요. 왜 그런지는 잘 모르겠지만요. http://rfriend.tistory.com/193