본문 바로가기
Data Analysis/Statistics

R-연관분석

by mansoorrr 2023. 12. 3.
  • 연관분석이란 상품의 구매, 서비스, 거래, 사건 등 간에 규칙을 발견하여 연관성을 파악하는 데이터마이닝 방법론
  • 효과적인 상품진열, 패키지 상품개발, 교차판매 전략, 기획상품의 결정 등에 사용됨
  • 장바구니분석, 서열분석이라고 불림
  • 측도
    • 지지도(Support): 전체 거래중 A와 B를 동시에 포함하는 거래의 비율: A ∩ B / 전체
    • 신뢰도(Confidence): A거래 비율중 A와 B가 같이 포함될 확률: 지지도 / P(A)
    • 향상도(Lift): A가 구매되지 않았을때 B가 구매될 확률보다 A가 구매됐을때 B가 구매될 확률이 얼마나 높은지의 증가비: P( B | A) / P(B) = 신뢰도 / P(B)
      • L > 1: 양의 상관관계 A와 B를 구매할 확률이 B만 구매할 확률보다 L배만큼 높음
      • L = 1: 상관없음
      • L < 1: 음의 상관관계 A와 B를 구매할 확률이 B만 구매할 확률보다 L배만큼 낮음
  • 가장 많이 사용되는 알고리즘으로 Apriori가 있음
    • 빈발항목집합: 최소지지도보다 큰 지지도 값을 갖는 품목의 집합
    • 모든 품목 집합에 대한 지지도를 모두 계산하지 않고 최소지지도 이상의 빈발항목집합을 찾은 후 연관규칙 계산
    • 아이템 개수가 많아지면 계산복잡도가 증가
    • arules 패키지에서 사용 가능
    • 연관분석을 사용하기 전에 트랜잭션 형태로 변형해 주어야 함
      • as(data, class): 데이터 형태 변형
        • data: 변경하고자 하는 데이터
        • class: 변경할 클래스 이름("transactions", "data.frame".....)
      • inspect(data): 트랜잭션 데이터 확인
    • 연관분석 실시
      • apriori(data, parameter, appearance, control)
        • data: 트랜잭션데이터, 매트릭스데이터
        • parameter
          • minlen: 최소아이템 개수
          • maxlen: 최대 아이템 개수
          • supp: 최소지지도
          • conf: 신뢰도(default=0.8)
      • inspect(data): 연관규칙 분석결과 확인

 

예시 1) 데이터 만들어 진행

#----------- 패키지 로드
install.packages("arules");
library(arules);

#----------- 데이터 만들기
#변수설정
id <- c(1, 2, 3, 4, 5, 6);
gender <- c("FEMALE", "MALE", "FEMALE", "FEMALE", "MALE", "FEMALE");
age <- c(20, 20, 40, 30, 40, 30);
rank <- c("Gold", "Silver", "Silver", "VIP", "Gold", "Gold");
mobile_app_use <- c("Y", "Y", "N", "Y", "N", "Y");
re_order <- c("Y", "N", "N", "Y", "N", "Y");

#데이터프레임 만들기
cust_tel <- cbind(id, gender, age, rank, mobile_app_use, re_order); #column 결합 
cust_tel <- data.frame(cust_tel); #데이터프레임
cust_tel_1 <- subset(cust_tel[,-1]); #데이터프레임 슬라이싱

 

생성한 데이터 프레임

 

#---------- 트랜잭션 변환
tran_cust <- as(cust_tel_1, "transactions");
tran_cust;
inspect(tran_cust);

트랜잭션 변환

 

#--------- apriori사용
#파라미터 정의(최소지지도 0.02 이상, 신뢰도 0.8, 최소집합 1, 최대집합 2)
params <- list(support=0.02, confidence=0.8, minlen=1, maxlen=2);

#규칙생성
rules <- apriori(tran_cust, parameter = params);

#규칙확인
inspect(rules);

#규칙해석
summary(rules);

 

  • apriori함수를 이용해 연관규칙을 생성한다. 생성된 규칙에 대한 요약 정보이다.
  • Parameter specification을 보면 code에서 지정한대로 support, confidence, minlen, maxlen인자 모두 적용된 것을 확인할 수 있다.
  • 규칙은 16개가 생성되었다.

규칙생성

 

  • inpect() 함수를 이용해 규칙을 확인한다.
  • 트랜잭션은 16개가 생성되었으며 각 트랜잭션당 지지도, 신뢰도, 향상도를 확인할 수 있다.
  • 첫번째 트랜잭션 해석 예시
    • rank가 vip이면서 age가 30일 확률은 16.7%이다.
    • rank=VIP 이면서 age=30일 확률이 age=30일 확률보다 3배 높다.

규칙확인

 

  • 16개 규칙은 2개의 값을 가지고 있다.
  • 최소 향상도는 1.5, 평균 지지도는 31%이다.

규칙해석

 

 

예시2) Groceries 데이터 활용

#--------------- 패키지 로드
install.packages("arules")
library(arules)

#--------------- 데이터로드(트랜잭션으로 변환되어 있음)
data("Groceries")
Groceries
inspect(Groceries[1:3])

트랜잭션 변환된 Groceries 데이터

 

#-------------- apriori 사용
#파라미터 설정
params <- list(
  supp=0.01, conf=0.3
);

#규칙생성
rules <- apriori(Groceries, parameter = params);

#연관규칙 결과 확인
inspect(rules);
inspect(sort(rules, by="lift", decreasing=T)[1:5]) #향상도기준 내림차순 5개

 

  • 코드에서와 같이 최소지지도를 0.01로, 신뢰도를 0.3으로 지정하여 apriori에 적용
  • 125개의 규칙이 생성됨
  • 향상도를 기준으로 내림차순 정렬한  연관규칙 5개만 확인

파라미터 적용 규칙생성

 

  • support는 좌항과 우항이 함께 구매될 확률
  • confidence는 좌항과 우항의 연관 관계의 정도
  • lift는 좌항의 제품 구매시 우항의 제품 구매할 확률이 n배 라는 의미

향상도기준 내림차순으로 정렬한 연관규칙 5개 출력

 

  • 출력된 규칙에서 [1]과 [4]는 lhs(좌항)과 rhs(우항)이 겹치는 것을 확인할 수 있다.
  • 중복되는 규칙은 없애기 위해 함수를 구현(arules패키지는 중복 가지치기 함수를 제공하지 않음)
drop_dup_rules <- function(rules) {
  test_rules_matrix <- is.subset(rules, rules, sparse=F) #lhs와 rhs결합 x, y축 동일한 행렬 만들기
  like_matrix <- lower.tri(test_rules_matrix, diag=T); #삼각함수를 이용해 test_rules_matrix과 모양 같은 bool행렬 만들기
  test_rules_matrix[like_matrix] <- NA; #bool행렬에서 True부분을 NA로 변경
  dup_rules <- colSums(test_rules_matrix, na.rm=T) >= 1; #컬럼별 합계 구하여 중복 체크
  pruned_rules <- rules[!dup_rules]#false인 컬럼만 살리기(중복없다는 뜻)
  return (pruned_rules);
}

 

  • 특정 rhs를 구매하게 만드는 lhs를 찾기 위한 연관규칙 생성
    • support(최소지지도): 0.001, confidence(신뢰도): 0.5, minlen(좌항과 우항을 합친 최소 물품 수: 2)
    • soda를 구매하게 만드는 lhs를 찾기
    • 실행결과를 나타내기
#----------------------우변의 구매를 이끌 아이템 세트 찾기
#파라미터 적용
params <- list(
  supp=.001,
  conf=.5,
  minlen=2
);

#soda를 구매하게 만드는 lhs찾기
appearance <- list(
  default="lhs", rhs="soda"
);

#실행결과 나타내기
control <- list(verbose=T);

#규칙생성
rules = apriori(
  data=Groceries,
  parameter=params,
  appearance=appearance,
  control=control
);

#중복제거 함수 적용
rules <- drop_dup_rules(rules);

#신뢰도 기준으로 내림차순 정렬
rules <- sort(rules, by="confidence", decreasing=F);

#연관 규칙 확인
inspect(rules);

 

  • 파리미터에 명시된대로 규칙 생성됨(control에서 verbose=T로 설정했기 때문에 해당 결과 나타남)
  • 중복 제거 전 43개 규칙이 생성됨

규칙생성 결과

 

  • 중복제거 후 41개의 규칙만 남음
  • 신뢰도 기준으로 오름차순 정렬 실시
  • coffee, misc.beverage를 함께 구매할 경우 soda를 구매하는 확률이 77%로 가장 높게 나타났다.

중복제거 후 신뢰도 기준 내림차순한 결과

 

  • 특정 lhs를 구매하게 만드는 rhs를 찾기 위해 연관규칙 생성
#최소지지도, 신뢰도, 최소집합 수 설정
params2 <- list(
  supp=0.001,
  conf=0.3,
  minlen=2
);

#특정 lhs를 찾기 위한 rhs
appearance2 <- list(
  default="rhs",
  lhs=c("yogurt", "sugar")
);

#실행결과 숨기기
control <- list(verbose=F);

#규칙생성
rules2 <- apriori(Groceries, parameter=params2, appearance=appearance2, control=control);

#중복제거
rules2 <- drop_dup_rules(rules2);

#신뢰도를 기준으로 오름차순 정렬한 규칙 확인
inspect(sort(rules2, by="confidence", decreasing = F));

 

  • control의 verbose를 FALSE로 설정했기 때문에 실행한 요약결과는 나타나지 않는다.
  • 규칙을 확인한 결과 총 6개의 규칙이 나타났다.
  • yogurt or sugar와 연관이 가장 높은 제품은 whole milk임을 알 수 있다.

 

 

예시 3) lotto데이터 활용

  • 859회 로또 당첨번호 가지고 있는 데이터
  • 변수설명
    • time_id: 회차
    • num1 ~ num6: 1번부터 6번까지의 번호
#데이터 로드
lotto <- read.csv("lotto.csv");
head(lotto);

로드된 데이터

 

  • num1 ~ num6는 회차당 6개의 숫자이므로 long form으로 데이터 변환
  • melt함수 사용
#데이터 형태 변환 패키지 로드
install.packages("reshape2");
library(reshape2);

#데이터 형태 변환: melt
lotto_melt <- melt(lotto, id.vars=1); #첫번째 열을 기준으로 melt
lotto_melt <- lotto_melt[,-2]; #두번째 열 삭제
str(lotto_melt); #변환된 데이터 확인

melt하여 정제한 데이터

 

  • apriori 함수를 적용하기 전 transaction데이터로 변환해야 함
  • transaction데이터로 변환하기 전 회차별 번호로 분리
#----------트랜잭션 데이터로 변환
#회차별 번호로 분리
lotto_sp <- split(lotto_melt$value, lotto_melt$time_id);
#회차별 트랜잭션 데이터로 변환
lotto_ts <- as(lotto_sp, "transactions");
#결과확인
inspect(lotto_ts[1:5]);

트랜잭션 데이터로 변환

 

  • 가장 많이 나타난 숫자 시각화: itemFrequencyPlot(x, topN, type)
  • 34번숫자가 가장 많은 빈도를 차지하고 나머지 숫자들은 다 비슷하다
itemFrequencyPlot(lotto_ts, topN=10, type="absolute") #절대빈도
itemFrequencyPlot(lotto_ts, topN=10) #상대도수(비율)

가장 많이 나타난 숫자 시각화

 

  • apriori 함수 적용
  • 최소지지도: .002, 최소신뢰도: .8, 최소조합 수: 2, 최대조합 수: 6개
  • 679개 규칙이 생성됨
#---------- apriori적용
install.packages("arules");
library(arules);

#파라미터 정의
apr_params <- list(
  supp=.002,
  conf=.8,
  minlen=2,
  maxlen=6
);

#규칙생성
rules1 <- apriori(lotto_ts, parameter=apr_params);

연관 규칙 생성 결과

 

  • 향상도를 기준으로 연관규칙 생성한 결과를 내림차순 정렬
  • 상위 30개만 데이터프레임으로 저장
  • summary를 이용하여 연관규칙 정보 확인
  • 연관 규칙은 총 679개가 도출됨
  • 트랜잭션 데이터는 859개이며 이는 회차 정보를 나타냄
  • 632개의 규칙은 4개의 숫자로 이루어져 있고, 47개의 규칙은 5개의 숫자로 이루어짐
  • 향상도(lift)의 최소값은 6.41로 꽤 높음
  • 숫자들의 교집합 확률인 지지도(support)는 평균 0.0023으로 나타남
#---------- 향상도 기준 내림차순 정렬 및 상위 30개 저장
sorted_rules1 <- sort(rules1, by="lift", decreasing=TRUE);
inspect(sorted_rules1[1:30]);

#데이터프레임으로 저장
top30 <- inspect(sorted_rules1[1:30]);
top30_df <- as(top30, "data.frame");
str(top30_df);

#---------- summary
summary(rules1);

lift 기준 내림차순 정렬 후 상위 30개 데이터프레임 변환 & 요약정보 확인

 

  • 34가 나오게 하는 숫자들의 조합을 찾고 인사이트 도출
  • 19개의 규칙이 도출되었다.
  • [1]번 규칙을 확인하면 7, 22, 31과 34가 함께 추출될 확률은 0.2%
  • 34만 뽑힐 확률보다 7, 22, 31과 34가 함께 추출될 확률이 6.41배 높음
  • 하지만 이 규칙은 순서를 고려하지 않고 단순히 조합에 대한 확률만을 고려한 규칙임
  • 따라서 향상도가 높은 조합의 숫자들이 추첨될 가능성이 높은것은 아님
#rhs=34인 규칙 추출
#방법1
most_freq_rules <- apriori(lotto_ts, parameter=apr_params,
                           appearance=list(
                             default="lhs",
                             rhs=c("34")
                           )
                           );
inspect(most_freq_rules);

#방법2
most2 <- subset(rules1, rhs %in% "34");
inspect(most2);

'Data Analysis > Statistics' 카테고리의 다른 글

Python_Statistics_Regression  (0) 2024.03.01
Python_Statistics_Chi-square  (0) 2023.12.15
Python_Statistics_Anova(분산분석)  (0) 2023.12.11
Python_Statistics_t-test  (1) 2023.12.07
R기초  (1) 2023.12.03