- 연관분석이란 상품의 구매, 서비스, 거래, 사건 등 간에 규칙을 발견하여 연관성을 파악하는 데이터마이닝 방법론
- 효과적인 상품진열, 패키지 상품개발, 교차판매 전략, 기획상품의 결정 등에 사용됨
- 장바구니분석, 서열분석이라고 불림
- 측도
- 지지도(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): 트랜잭션 데이터 확인
- as(data, class): 데이터 형태 변형
- 연관분석 실시
- apriori(data, parameter, appearance, control)
- data: 트랜잭션데이터, 매트릭스데이터
- parameter
- minlen: 최소아이템 개수
- maxlen: 최대 아이템 개수
- supp: 최소지지도
- conf: 신뢰도(default=0.8)
- inspect(data): 연관규칙 분석결과 확인
- apriori(data, parameter, appearance, control)
예시 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])
#-------------- 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배 라는 의미
- 출력된 규칙에서 [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); #변환된 데이터 확인
- 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);
- 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 |