본문 바로가기

카테고리 없음

19일차 - 5월 6일

멤버십 기획 프로젝트 

 

 

 

 

customer_r <- read_excel("C:\\rstudy\\day12\\membership_data\\customer_r.xlsx")
View(customer_r)
colnames(customer_r) <- tolower(colnames(customer_r))
colnames(reservation_r) <- tolower(colnames(reservation_r))
colnames(order_info_r) <- tolower(colnames(order_info_r))
colnames(item_r) <- tolower((colnames(item_r)))
reservation_r <- read_excel("C:\\rstudy\\day12\\membership_data\\reservation_r.xlsx")
order_info_r <- read_excel("C:\\rstudy\\day12\\membership_data\\order_info_r.xlsx")
item_r <- read_excel("C:\\rstudy\\day12\\membership_data\\item_r.xlsx")
library(dplyr)
library(ggplot2)
#지점별 예약 건수 빈도표
table(reservation_r$branch)
#주문 취소되지 않은 경우만 선택
no_cancel_data <- reservation_r %>% filter(cancel == "N")
#주문 취소되지 않은 예약 건의 부서별 빈도표
table(no_cancel_data$branch)
#데이터 분석을 위해 원천 데이터 가공(전처리)
#reserv_no를 키로 예약, 주문 테이블 연결
df_f_join_1 <- inner_join(reservation_r, order_info_r, by = "reserv_no")
#item_id를 키로 df_f_join_1, 메뉴 정보 테이블 연결
df_f_join_2 <- inner_join(df_f_join_1,item_r,by = "item_id")
head(df_f_join_2)#테이블 세 개가 이너 조인된 것을 확인
#강남, 마포, 서초 지점만 선택
df_branch_sales <- df_f_join_2 %>% 
  filter(branch == "강남" | branch == "마포" | branch == "서초") %>% 
  group_by(branch, product_name) %>% #부서 이름과 메뉴 이름으로 그룹화 
  summarise(sales_amt = sum(sales) / 1000) #매출 합산
#누적 막대 그래프 그리기
ggplot(df_branch_sales, aes(x = "", y = sales_amt, fill = product_name)) + 
  facet_grid(facets = . ~ branch) + #면분할 함수 branch 기준으로 분할
  geom_bar(stat = "identity")
#파이차트로 그리기
ggplot(df_branch_sales, aes(x = "", y = sales_amt, fill = product_name)) +
  facet_grid(facets = . ~branch) +
  geom_bar(stat = "identity") + 
  coord_polar("y", start = 0) #파이차트그리기
#reserv_no를 키로 예약, 주문 테이블 연결
df_f_join_1 <- inner_join(reservation_r, order_info_r, by = "reserv_no")
#item_id를 키로 df_f_join_1, 메뉴 정보 테이블 연결
df_f_join_2 <- inner_join(df_f_join_1,item_r, by = "item_id")
#주요 지점만 선택
df_branch_items <- df_f_join_2 %>% filter(branch == "강남" | branch == "마포" | branch == "서초")
#교차 빈도표 생성
table(df_branch_items$branch, df_branch_items$product_name)
#데이터 프레임 형태로 구조형 변환
df_branch_items_table <- as.data.frame(table(df_branch_items$branch, df_branch_items$product_name))
#데이터 분속을 위해 데이터 가공
df_branch_items_percent <- df_branch_items_table %>% 
  group_by(df_branch_items_table$Var1) %>% 
  mutate(percent_items = Freq/sum(Freq) * 100) #주문 비율을 계산해서 열 생성 
head(df_branch_items_percent) #percent_items열이 생성된 것을확인

#누적 막대 그래프를 그려 gg변수에 담음
gg <- ggplot(df_branch_items_percent, aes(x = Var1, y = percent_items, group = Var1, fill = Var2)) +
  geom_bar(stat = "identity")
#제목과 범례 이름 지정
gg <- gg + 
  labs(title = "지점별 주문 건수 그래프", x = "지점", y = "메뉴 아이템 판매비율", fill = "메뉴 아이템")
gg

#테이블조인
#reserv_no를 키로 예약, 주문 테이블 연결
df_rfm_join_1 <- inner_join(reservation_r, order_info_r, by = "reserv_no")
head(df_rfm_join_1)#조인된 테이블 확인
#고객 번호별 방문 횟수(F)와 매출(M)정리
df_rfm_data <- df_rfm_join_1 %>% 
  group_by(customer_id) %>% 
  summarise(visit_sum = n_distinct(reserv_no), sales_sum = sum(sales) / 1000) %>% 
  arrange(customer_id)
df_rfm_data #데이터 확인
summary(df_rfm_data)
#상자 그림 그리기(방문횟수상자그림)

ggplot(df_rfm_data, aes(x= "", y = visit_sum)) + 
  geom_boxplot(width = 0.8, outlier.size = 2, outlier.colour = "red") + 
  labs(title = "방문 횟수 상자그림", x="빈도", y="방문횟수")

#매출상자그림
ggplot(df_rfm_data, aes(x= "", y = sales_sum)) + 
  geom_boxplot(width = 0.8, outlier.size = 2, outlier.colour = "red") + 
  labs(title = "매출 상자그림", x="매출", y="금액")

#방문 횟수 60%와 90%에 해당하는 분위수 찾기

quantile(df_rfm_data$visit_sum, probs = c(0.6, 0.9))

#매출 60%와 90%에 해당하는 분위수 찾기
quantile(df_rfm_data$sales_sum, probs = c(0.6, 0.9))

#총 방문 횟수와 총 매출 합

total_sum_data <- df_rfm_data %>% 
  summarise(t_visit_sum = sum(visit_sum), t_sales_sum = sum(sales_sum))
#우수 고객 이상의 방문 횟수와 매출 합

loyalty_sum_data <- df_rfm_data %>% 
  summarise(l_visit_sum = sum(ifelse(visit_sum > 2, visit_sum, 0)), l_sales_sum = sum(ifelse(sales_sum > 135, sales_sum, 0)))

#우수 등급 이상 기준인 방문 2초과이면 방문 횟수를 합합니다.
#우수 등급 이상 기준인 매출 135초과이면 매출을 합합니다.
#우수 등급 합 / 전체 등급 합


#차지하는 비율 확인
loyalty_sum_data / total_sum_data

#reserv_no를 키로 예약, 주문 테이블 연결
df_f_join_1 <- inner_join(reservation_r, order_info_r, by = "reserv_no")
#item_id를 키로 df_f_join_1, 메뉴 정보 테이블 연결
df_f_join_2 <- inner_join(df_f_join_1, item_r, by = "item_id")
target_item <- c("M0005", "M0009")#스테이크와 와인
#스테이크와 메뉴 아이템 동시 주문 여부 확인
df_stime_order <- df_f_join_2 %>% 
  filter((item_id %in% target_item)) %>%  #스테이크나 와인을 주문한 경우 선택
  group_by(reserv_no) %>%                 #예약 번호로 그룹화
  mutate(order_cnt = n()) %>%             #그룹화된 행 세기
  distinct(branch, reserv_no, order_cnt) %>%  #중복 예약 번호는 하나만 출력
  filter(order_cnt == 2) %>%              #2인 경우 선택(스테이크와 와인을 동시 주문한 경우)
  arrange(branch)
#동시 주문인 경우의 예약 번호 데이터셋(12건)
df_stime_order

#동시 주문한 예약 번호만 담는 stime_order변수 생성
stime_order_rsv_no <- df_stime_order$reserv_no #예약 번호만 선택

#동시 주문 예약 번호이면서 스테이크와 와인일 경우만 선택
df_stime_sales <- df_f_join_2 %>% 
  filter((reserv_no %in% stime_order_rsv_no) & (item_id %in% target_item)) %>% 
  group_by(reserv_no, product_name) %>%    #예약 번호와 메뉴 아이템으로 그룹화
  summarise(sales_amt = sum(sales) / 1000) %>% #매출 합계 요약 계산
  arrange(product_name, reserv_no) #메뉴 아이템, 예약 번호 기준으로 정렬

#동시 주문 12건이므로 매출 합계 24개 생성(스테이크+와인)
df_stime_sales

steak <- df_stime_sales %>% filter(product_name == "STEAK") # 스테이크 정보만 담음
wine <- df_stime_sales %>% filter(product_name == "WINE") #와인 정보만 담음
plot(steak$sales_amt, wine$sales_amt) #스테이크와 와인의 매출 상관도 그리기 
cor.test(steak$sales_amt, wine$sales_amt) #상관관계 확인
#유의확률 0.000002438
#상관계수 0.94



#고객별 스테이크 주문 여부 확인
#(A) 모든 고객의 예약 번호 데이터셋 생성
df_rsv_customer <- reservation_r %>% 
  select(customer_id, reserv_no) %>% #고객별 모든 예약 번호 선택 
  arrange(customer_id, reserv_no)

head(df_rsv_customer) #고객별 예약 번호 확인

#(B) 스테이크 주문 예약 번호 데이터셋 생성
df_steak_order_rsv_no <- order_info_r %>% 
  filter(item_id == "M0005") %>%  #스테이크 주문이면
  mutate(steak_order = "Y") %>%   #steak_order 열 데이터를 'Y'로 만듦
  arrange(reserv_no)
head(df_steak_order_rsv_no) #데이터셋 확인

#고객의 모든 예약 번호(A)에 대해 스테이크 주문한 예약번호(B)를 레프트 조인
df_steak_order_1 <- left_join(df_rsv_customer, df_steak_order_rsv_no, by = "reserv_no") %>% 
group_by(customer_id) %>%   #고객 번호로 그룹화하여(182명)
  mutate(steak_order = ifelse(is.na(steak_order), "N","Y")) %>% #주문 여부가 NA이면 N, Y이면 Y로 바꿈 
  summarise(steak_order = max(steak_order)) %>% #최댓값만 취함
  arrange(customer_id)


#최종 정리된 고객별 스테이크 주문 여부
df_dpd_var <- df_steak_order_1
#종속 변수, 최종 고객 182명의 스테이크 주문여부 결과 확인
df_dpd_var

#ifelse(조건식, TRUE일 때 값, FALSE일 때 값)
#steak_order가 NA인지 여부, NA이면 TRUE를 반환하고 아니면 FALSE를 반환 
#최댓값을 구하는 함수

#결측치 제거
df_customer <- customer_r %>% filter(!is.na(sex_code))
#성별이 없으면 (NA) 고객 번호 제거

#고객 테이블과 예약 테이블 customer_id를 키로 이너 조인
df_table_join_1 <- inner_join(df_customer, reservation_r, by = "customer_id")
#df_table_join_1과 주문 테이블의 reserv_no를 키로 이너 조인
df_table_join_2 <- inner_join(df_table_join_1, order_info_r, by = "reserv_no")
str(df_table_join_2) #df_table_join_2 테이블 구조 확인
#성별 정보(sex_code)가 NA가 아니라면(!)
#고객 정보, 성별 정보와 방문 횟수, 방문객 수, 매출 합을 요약(코드 풀이에서 자세히 설명)
df_table_join_3 <- df_table_join_2 %>% 
  group_by(customer_id, sex_code, reserv_no, visitor_cnt) %>% 
  summarise(sales_sum = sum(sales)) %>% 
  group_by(customer_id, sex_code) %>% 
  summarise(visit_sum = n_distinct(reserv_no), visitor_sum = sum(visitor_cnt), sales_sum = sum(sales_sum) / 1000) %>% 
  arrange(customer_id)

df_idp_var <- df_table_join_3 #독립변수
df_idp_var #독립변수 확인(142행)

#분석에 필요한 열만 그룹핑해서 정리합니다.
#중복이 아닌 값을 카운팅하는 함수입니다. 여기에서는 중복이 아닌 주문 예약 번호를 셉니다. 즉, 방문 횟수라고 생각할 수 있습니다. 


#독립변수데이터셋에 종속 변수 데이터셋 이너 조인
df_final_data <- inner_join(df_idp_var, df_dpd_var, by = "customer_id")
#의사 결정 나무 함수를 사용하려고 열 구조를 팩터형으로 바꿈
df_final_data$sex_code <- as.factor(df_final_data$sex_code)
df_final_data$steak_order <- as.factor(df_final_data$steak_order)

df_final_data <- df_final_data[,c(2:6)] #의사결정나무에 필요한 열만 선택
df_final_data #최종 분석용 데이터셋 확인

install.packages("rpart")
library(rpart)
install.packages("caret")
library(caret)
install.packages("e1071")
library(e1071)

#난수를 생성할 때 계속 무작위수를 생성하지 않고 1만번대겂을 고정으로 가져옴 
set.seed(10000)
#80%데이터는 train을 위해 준비하고 20%데이터는 test를 위해 준비함
train_data <- createDataPartition(y = df_final_data$steak_order, p = 0.8, list = FALSE)
train <- df_final_data[train_data,]
test <- df_final_data[-train_data,]
#rpart를 사용해서 의사 결정 나무 생성
decision_tree <- rpart(steak_order~., data= train)
#decision_tree내용 확인
decision_tree

#데이터 나누기 함수입니다. df_final_data의 steak_order열을 기준으로 80%의 행 데이터를 나눕니다. list = FALSE는 리스트 구조로 출력하지 않겠다는 의미입니다. 
#훈련 데이터셋을 제외한 데이터 입니다. 즉, 80%외 20%를 의미합니다. 


#훈련데이터는 142개 중 115개 (약 80%)
#1번 노드, 115개 중에서 N 값이라면 44개를 설명할 수 없음(즉, Y가 44개)
#2번 노드, sales_sum이 55.5보다 작은 것이 37개 있고 N일 때 이중에 설명할 수 없는 것을 2개(Y)
#3번 노드, sales_sum이 55.5 이상인 것이 78개 있고 Y일 떄 이 중에 설명할 수 없는 것은 36개(N)

predicted <- predict(decision_tree, test, type = 'class')
confusionMatrix(predicted, test$steak_order)

plot(decision_tree, margin = 0.1)#의사결정나무 그리기
text(decision_tree)#의사결정나무텍스트쓰기



install.packages("rattle") #패키지 설치
library(rattle) # 패키지 로딩

fancyRpartPlot(decision_tree)#의사결정나무깔끔하게 그리기