티스토리 뷰

Data/R

연관분석 (Association Analysis)

ellie.strong 2021. 7. 5. 01:11
728x90

데이터 설명

이름 : Transactions from a bakery

링크 : Transactions from a bakery | Kaggle

- 베이커리에서 판매된 상품의 트랜잭션 기록 데이터이다.

bread<-read.csv("BreadBasket_DMS.csv", header=T)
head(bread)

str(bread)

Date, Time, Transaction(ID), Item의 4개의 변수를 가지며, 총 21293개의 데이터를 포함하고 있다. 
연관 규칙을 분석하기위해서는 4개의 변수 중 Transction(ID)와 Item 2개의 변수를 사용한다. 

 

데이터 불러오기

- 필요한 패키지를 설치한다. 

# 연관 분석을 위해
install.packages("arules")
library(arules)

- read.transactions() 함수를 이용해 transaction 객체의 형태로 데이터를 불러온다.

- 참고 : read.transactions function - RDocumentation

trans<-read.transactions("BreadBasket_DMS.csv", format="single", cols=c(3,4), sep=",", rm.duplicates=T)
trans

6614개의 트랜잭션과 104개의 항목(상품)이 생성되었다. 

 

트랜잭션 데이터 보기

- inspect() 함수를 이용해 트렌젝션 객체를 배열 형태로 출력할 수 있다. 

- 데이터 양이 많아 head()함수를 이용하여 상위 6개의 트렌젝션만 출력하였다. 

inspect(head(trans))

 

데이터 분석

1. 상품에 따른 분포 살펴보기

- itemFrequencyPlot() 함수를 이용하여 상품의 절대적/상대적 분포를 bar plot 형태로 나타낼 수 있다. 

itemFrequencyPlot(trans, topN=15, type="absolute", xlab="Item Name", ylab="Frequency (absolute)", main="Asolute Item Frequency Plot", col="pink")
itemFrequencyPlot(trans, topN=15, type="relative", xlab="Item Name", ylab="Frequency (relative)", main="Relative Item Frequency Plot", col="pink")

베이커리에서 판매된 상품 중 Coffee가 가장 많이 판매된 것을 알 수 있으며, 그 다음이 Bread, Tea인 것을 알 수 있다.  

 

2. 시간에 따른 분포 살펴보기

- 데이터를 .csv 파일로 불러온다. 

trans_csv<-read.csv("BreadBasket_DMS.csv")

- 필요한 패키지를 설치한다. 

# %>% operator를 사용하기 위해
library(magrittr) 

# month()를 사용하기 위해
install.packages("lubridate")
library(lubridate)

# mutate(), summarise()를 사용하기 위해
install.packages("dplyr")
library(dplyr) 

# ggplot()을 사용하기 위해
install.packages("ggplot2")
library(ggplot2) 

 

2-1. 월별 트랜잭션 분포 살펴보기

trans_csv %>%
  mutate(Month=as.factor(month(Date))) %>%
  group_by(Month) %>%
  summarise(Transactions=n_distinct(Transaction)) %>%
  ggplot(aes(x=Month, y=Transactions)) +
  geom_bar(stat="identity", fill="pink", 
           show.legend=FALSE, colour="black") +
  geom_label(aes(label=Transactions)) +
  labs(title="Transactions per month") +
  theme_bw() 

우리가 사용하는 데이터가 2016.10.30 - 2017.04.09 사이의 데이터이기 때문에 4월과 10월의 데이터가 적을 수 밖에 없다는 것을 참고하자. 

 

2-2. 요일별 트랜잭션 분포 살펴보기

trans_csv %>%
  mutate(WeekDay=as.factor(weekdays(as.Date(Date)))) %>%
  group_by(WeekDay) %>%
  summarise(Transactions=n_distinct(Transaction)) %>%
  ggplot(aes(x=WeekDay, y=Transactions)) +
  geom_bar(stat="identity", fill="pink", 
           show.legend=FALSE, colour="black") +
  geom_label(aes(label=Transactions)) +
  labs(title="Transactions per weekday") +
  scale_x_discrete(limits=c("Monday", "Tuesday", "Wednesday", "Thursday",
                            "Friday", "Saturday", "Sunday")) +
  theme_bw() 

토요일에 유독 손님이 많다는 것을 확인할 수 있다. 
그래프가 그려지지 않는 문제가 발생.....

 

2-3. 시간별 트랜잭션 분포 살펴보기

trans_csv %>%
  mutate(Hour=as.factor(hour(hms(Time)))) %>%
  group_by(Hour) %>%
  summarise(Transactions=n_distinct(Transaction)) %>%
  ggplot(aes(x=Hour, y=Transactions)) +
  geom_bar(stat="identity", fill="pink", show.legend=FALSE, colour="black") +
  geom_label(aes(label=Transactions)) +
  labs(title="Transactions per hour") +
  theme_bw()

베이커리의 손님 대부분이 오전 8시에서 오후 5시 사이에 분포함을 볼 수 있으며, 특히 오전 11시 경에 손님이 가장 분빈다는 것을 알 수 있다. 

 

Apriori 알고리즘으로 연관규칙 찾기

1. 최소 지지도(Support)와 최소 신뢰도(Confidence) 선택하기

- 각각 {0.1, 0.05, 0.01, 0.005}의 지지도와  {0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1}의 신뢰도에 대한 모든 규칙의 개수를 저장한다. 

# Support and confidence values
supportLevels <- c(0.1, 0.05, 0.01, 0.005)
confidenceLevels <- c(0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1)

# Empty integers 
rules_sup10 <- integer(length=9)
rules_sup5 <- integer(length=9)
rules_sup1 <- integer(length=9)
rules_sup0.5 <- integer(length=9)

# Apriori algorithm with a support level of 10%
for (i in 1:length(confidenceLevels)) {
  
  rules_sup10[i] <- length(apriori(trans, parameter=list(sup=supportLevels[1], 
                                   conf=confidenceLevels[i], target="rules")))
  
}

# Apriori algorithm with a support level of 5%
for (i in 1:length(confidenceLevels)){
  
  rules_sup5[i] <- length(apriori(trans, parameter=list(sup=supportLevels[2], 
                                  conf=confidenceLevels[i], target="rules")))
  
}

# Apriori algorithm with a support level of 1%
for (i in 1:length(confidenceLevels)){
  
  rules_sup1[i] <- length(apriori(trans, parameter=list(sup=supportLevels[3], 
                                  conf=confidenceLevels[i], target="rules")))
  
}

# Apriori algorithm with a support level of 0.5%
for (i in 1:length(confidenceLevels)){
  
  rules_sup0.5[i] <- length(apriori(trans, parameter=list(sup=supportLevels[4], 
                                    conf=confidenceLevels[i], target="rules")))
  
}

- 규칙의 개수를 보여주는 plot을 살펴본다. 

# grid.arrange()를 사용하기 위해
install.packages("gridExtra")
library(gridExtra)
# Number of rules found with a support level of 10%
plot1 <- qplot(confidenceLevels, rules_sup10, geom=c("point", "line"), 
               xlab="Confidence level", ylab="Number of rules found", 
               main="Apriori with a support level of 10%") +
  theme_bw()

# Number of rules found with a support level of 5%
plot2 <- qplot(confidenceLevels, rules_sup5, geom=c("point", "line"), 
               xlab="Confidence level", ylab="Number of rules found", 
               main="Apriori with a support level of 5%") + 
  scale_y_continuous(breaks=seq(0, 10, 2)) +
  theme_bw()

# Number of rules found with a support level of 1%
plot3 <- qplot(confidenceLevels, rules_sup1, geom=c("point", "line"), 
               xlab="Confidence level", ylab="Number of rules found", 
               main="Apriori with a support level of 1%") + 
  scale_y_continuous(breaks=seq(0, 50, 10)) +
  theme_bw()

# Number of rules found with a support level of 0.5%
plot4 <- qplot(confidenceLevels, rules_sup0.5, geom=c("point", "line"), 
               xlab="Confidence level", ylab="Number of rules found", 
               main="Apriori with a support level of 0.5%") + 
  scale_y_continuous(breaks=seq(0, 130, 20)) +
  theme_bw()

# Subplot
grid.arrange(plot1, plot2, plot3, plot4, ncol=2)

- 위와 같은 네개의 그래프를 색상으로 구분하여 하나의 그래프로 나타낼 수 있다. 

# Data frame
num_rules <- data.frame(rules_sup10, rules_sup5, rules_sup1, rules_sup0.5, confidenceLevels)

# Number of rules found with a support level of 10%, 5%, 1% and 0.5%
ggplot(data=num_rules, aes(x=confidenceLevels)) +
  
  # Plot line and points (support level of 10%)
  geom_line(aes(y=rules_sup10, colour="Support level of 10%")) + 
  geom_point(aes(y=rules_sup10, colour="Support level of 10%")) +
  
  # Plot line and points (support level of 5%)
  geom_line(aes(y=rules_sup5, colour="Support level of 5%")) +
  geom_point(aes(y=rules_sup5, colour="Support level of 5%")) +
  
  # Plot line and points (support level of 1%)
  geom_line(aes(y=rules_sup1, colour="Support level of 1%")) + 
  geom_point(aes(y=rules_sup1, colour="Support level of 1%")) +
  
  # Plot line and points (support level of 0.5%)
  geom_line(aes(y=rules_sup0.5, colour="Support level of 0.5%")) +
  geom_point(aes(y=rules_sup0.5, colour="Support level of 0.5%")) +
  
  # Labs and theme
  labs(x="Confidence levels", y="Number of rules found", 
       title="Apriori algorithm with different support levels") +
  theme_bw() +
  theme(legend.title=element_blank())

지지도 10%, 5%의 경우 생성되는 규칙이 매우 적으며, 반대로 지지도 0.5%의 경우 생성되는 규칙이 너무 많다는 것을 확인 할 수 있다. 따라서 우리는 지지도 1%를 선택 할 것이며,  최소 50%의 신뢰도에서 15개 정도의 규칙이 생성되므로 그 이상으로 신뢰도를 선택 할 것이다. 

 

2. 연관 규칙 생성하기

- apriori 알고리즘으로 최소 지지도 1%(0.01), 최소 신뢰도 50%(0.05) 이상인 연관 규칙들을 생성한다. 

rules_sup1_conf50 <- apriori(trans, parameter=list(sup=supportLevels[3], conf=confidenceLevels[5], target="rules"))

 

- 생성된 규칙 살펴보기

inspect(rules_sup1_conf50)

Coverage : 왼쪽 변수 개수 / 전체 개수

- sort() 함수를 이용하여 지지도에 대한 내림차순 정렬로 살펴볼 수 있다. 

inspect(sort(rules_sup1_conf50))

- 리프트(Lift) 기준으로 상위 5개의 규칙들을 살펴볼 수 있다. 

inspect(head(sort(rules_sup1_conf50,by="lift"),5)) 

생성된 연관 규칙들을 살펴본 결과 이 베이커리의 손님들이 일단 Coffee를 매우 좋아한다는 것을 알 수 있으며, 
Toast를 산 손님의 72%가 커피를 샀으며, Spanish Brunch를 산 손님의 63%가 커피를 샀다는 것을 알 수 있다. 

 

3. 연관 규칙 시각화하기

# 연관 규칙을 plot에 적용시키기 위해
install.packages("arulesViz")
library(arulesViz)

- Scatter Plot

plot(rules_sup1_conf50, measure=c("support", "lift"), shading="confidence")

격자가 자동으로 생성되는 문제가 발생한다.....

- Graph Plot (default layout)

plot(rules_sup1_conf50, method="graph")

- Graph Plot (circular layout)

plot(rules_sup1_conf50, method="graph", control=list(layout=igraph::in_circle()))

- Grouped Matrix Plot

plot(rules_sup1_conf50, method="grouped")

 


Ref.

Market Basket Analysis | Kaggle

[R] 비지도 학습의 방법 : 연관분석 (Association Analysis) (tistory.com)

R, Python 분석과 프로그래밍의 친구 (by R Friend) :: [R 연관규칙 (Association Rule)] R arules package로 연관규칙 분석하기 (tistory.com)

 

728x90
댓글
공지사항
최근에 올라온 글