R
확률 - 예제
긔
2020. 7. 13. 17:53
확률(Probability) 실전예제
10년치 편의점 판매 데이터 분석하기
-
1500만건
-
특정 상품을 정해 시간당 몇 개씩 팔리는 지 분석
-
확률실험 관측값(팔린갯수)를 확률변수로 사용 ★
-
확률변수 : 무작위 실험을 했을 때, 특정 확률로 발생하는 각각의 결과를 수치적 값으로 표현하는 변수
-
ex) 동전 2개를 던져 숫자가 나오는 경우의 확률변수 = [0, 1, 2] / 주사위 2개를 던져 나온 눈의 합의 평균을 구할때 확률변수 = [2~12]
시간당 판매갯수 확률변수로 분석하기
# 대량의 데이터 빠르게
library(data.table)
# 데이터 로드 - fread()로 data.frame 만들기
df <- fread('r-ggagi-data/example_conveniencestore.csv', encoding = 'UTF-8', data.table=F)
head(df)
Date | sellproduct | company | payment | margin | |
---|---|---|---|---|---|
<chr> | <chr> | <chr> | <chr> | <dbl> | |
1 | 2006-01-01 07:00:02 | 보가리스웨트 620미리리터(P) | 동화오츠카㈜ | 체크카드 | 0.11 |
2 | 2006-01-01 07:00:14 | 막스 500미리리터(캔) | 블랙맥주㈜ | 현금 | 0.04 |
3 | 2006-01-01 07:00:42 | 맛좋은우유 GT 1리터(팩) | 서양유업㈜ | 체크카드 | 0.13 |
4 | 2006-01-01 07:00:48 | 육개장사발탕면 86g(컵) | ㈜낭심 | 신용카드 | 0.28 |
5 | 2006-01-01 07:01:14 | 제주도삼다수<U+00A0>2리터(P) | ㈜낭심 | 신용카드 | 0.22 |
6 | 2006-01-01 07:01:24 | 경기도장수생막걸리 750미리리터(P) | 경기도탁주제조협회 | 현금 | 0.30 |
# 표본 만들기
S <- df[sample(nrow(df), 5000), ]
str(S)
'data.frame': 5000 obs. of 5 variables:
$ Date : chr "2013-07-13 08:10:25" "2007-02-27 11:58:21" "2011-04-01 20:02:11" "2013-04-07 08:17:57" ...
$ sellproduct: chr "가스큐팩 1.6리터(P)" "핫개컨디션파워 100미리리터(병)" "팔성사이다<U+00A0>500미리리터(P)" "참이슬로 360미리리터(병)" ...
$ company : chr "오비이락맥주㈜" "디제이제당㈜" "팔성음료㈜" "㈜잔루" ...
$ payment : chr "체크카드" "교통카드" "교통카드" "현금" ...
$ margin : num 0.09 0.3 0.04 0.06 0.32 0.25 0.21 0.25 0.29 0.08 ...
# 분석 상품 선택 - 가장 많이 팔린 상품
sort(table(S$sellproduct)) # 가스큐팩 1.6리터(P)
새로운라면큰사발 114g(컵) 바리스타라떼 250미리리터(컵)
26 40
딸기속우유 310미리리터(팩) 옥수수차 500미리리터(P)
42 42
조르지아오리지널 240미리리터(캔) 카페라떼와일드 200미리리터(컵)
42 42
팔성사이다<U+00A0>1.5리터(P) 가스라이트큐팩<U+00A0>1.6리터(P)
43 45
간다다프리미엄블렌드 275미리리터(캔) 구카카콜 250미리리터(캔)
46 46
비타528 100미리리터(병) 아이리시스<U+00A0>500미리리터(P)
46 46
TOP스위트블랙커피 275미리리터(캔) 우유속에카푸치노 310미리리터(팩)
48 48
가스 640미리리터(병) 가스큐팩 1000미리리터(P)
49 49
딸기짱우유 240미리리터(팩) 힘에이드마운틴블라스트 600미리리터(P)
49 49
아이리시스<U+00A0>2리터(P) 육개장사발탕면 86g(컵)
50 50
메지밀B 190미리리터(병) 맛좋은우유 GT 1리터(팩)
52 53
보가리스웨트 620미리리터(P) 경기도우유 200미리리터(팩)
53 54
막스 355미리리터(캔) 글라소비타민물공급<U+00A0>500미리리터(P)
54 55
세계콘 170미리리터 팔성사이다<U+00A0>500미리리터(P)
58 58
굿이브닝케어 100미리리터(병) 구카카콜 500미리리터(P)
63 86
마지막처럼 360미리리터(병) 구카카콜 1.5리터(P)
90 92
화이트 500미리리터((캔) 레잇비마일드 185미리리터(캔)
94 96
화이트피처 1.6리터(P)<U+00A0> 경기도우유 1리터(팩)
98 99
화이트 355미리리터(캔)<U+00A0> 야명808 140미리리터(캔)
102 103
막스 500미리리터(캔) 제주도삼다수<U+00A0>2리터(P)
104 104
경기도장수생막걸리 750미리리터(P) 먹스피쳐 1.6리터(P)
105 113
제주도사다수 500미리리터(P) 참이슬로 360미리리터(병)
115 158
핫개컨디션파워 100미리리터(병) 첨이슬fresh 360미리리터(병)
180 247
굿스맥주 500미리리터(캔) 굿스맥주 355미리리터(캔)
314 374
바나나멋우유 240미리리터(P) 가스큐팩 1.6리터(P)
420 508
# 가스큐팩 1.6리터(P) 시간당 판매 조사
#날짜 문자열 처리
library(stringr)
Warning message:
"package 'stringr' was built under R version 4.0.2"
head(S$Date,3)
- '2013-07-13 08:10:25'
- '2007-02-27 11:58:21'
- '2011-04-01 20:02:11'
S$time <- str_split_fixed(S$Date, " ", 2)[,2]
S$hour <- str_split_fixed(S$time, ":", 3)[,1]
head(S, 1)
Date | sellproduct | company | payment | margin | time | hour | |
---|---|---|---|---|---|---|---|
<chr> | <chr> | <chr> | <chr> | <dbl> | <chr> | <chr> | |
11879271 | 2013-07-13 08:10:25 | 가스큐팩 1.6리터(P) | 오비이락맥주㈜ | 체크카드 | 0.09 | 08:10:25 | 08 |
# 가스큐팩 1.6리터(P) 추출
library(dplyr)
Warning message:
"package 'dplyr' was built under R version 4.0.2"
Attaching package: 'dplyr'
The following objects are masked from 'package:data.table':
between, first, last
The following objects are masked from 'package:stats':
filter, lag
The following objects are masked from 'package:base':
intersect, setdiff, setequal, union
S <- as_tibble(S)
S2 <- filter(S, sellproduct == "가스큐팩 1.6리터(P)")
#S3 <- S[S$sellproduct == "가스큐팩 1.6리터(P)",]
#head(S3)
#S4 <- subset(S, subset = S$sellproduct == "가스큐팩 1.6리터(P)")
#head(S4)
str(S2)
tibble [508 x 7] (S3: tbl_df/tbl/data.frame)
$ Date : chr [1:508] "2013-07-13 08:10:25" "2008-05-05 22:31:16" "2012-05-05 10:26:03" "2012-02-12 09:05:33" ...
$ sellproduct: chr [1:508] "가스큐팩 1.6리터(P)" "가스큐팩 1.6리터(P)" "가스큐팩 1.6리터(P)" "가스큐팩 1.6리터(P)" ...
$ company : chr [1:508] "오비이락맥주㈜" "오비이락맥주㈜" "오비이락맥주㈜" "오비이락맥주㈜" ...
$ payment : chr [1:508] "체크카드" "신용카드" "신용카드" "교통카드" ...
$ margin : num [1:508] 0.09 0.09 0.09 0.09 0.09 0.09 0.09 0.09 0.09 0.09 ...
$ time : chr [1:508] "08:10:25" "22:31:16" "10:26:03" "09:05:33" ...
$ hour : chr [1:508] "08" "22" "10" "09" ...
# 시간대별 도수 : 윗줄 = 시간 / 아랫줄 = 판매된 갯수
freq <- table(S2$hour)
freq
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23
19 29 20 16 25 13 11 17 17 23 21 21 22 29 19 21 25 20 23 21 28 33 16 19
# 확률 변수 X 선택
rv <- as.vector(freq)
rv <- rv[!duplicated(rv)] # 중복값 제거
rv <- sort(rv)
rv
- 11
- 13
- 16
- 17
- 19
- 20
- 21
- 22
- 23
- 25
- 28
- 29
- 33
# 확률 변수별 비율
prv <- prop.table(rv)
prv
- 0.0397111913357401
- 0.0469314079422383
- 0.0577617328519856
- 0.0613718411552347
- 0.0685920577617329
- 0.0722021660649819
- 0.075812274368231
- 0.0794223826714801
- 0.0830324909747292
- 0.0902527075812274
- 0.101083032490975
- 0.104693140794224
- 0.11913357400722
# 각각의 기대값
exps <- rv * prv
exps
- 0.436823104693141
- 0.610108303249097
- 0.924187725631769
- 1.04332129963899
- 1.30324909747292
- 1.44404332129964
- 1.59205776173285
- 1.74729241877256
- 1.90974729241877
- 2.25631768953069
- 2.83032490974729
- 3.03610108303249
- 3.93140794223827
# 확률변수의 평균 = (확률변수 * 확률(비율))의 총합
sum(exps)
23.0649819494585
묶음행사 상품 판매 데이터 분석하기
-
이벤트 상품 8개 중 6개를 골라 세트 구입
-
중복해서 구입 가능 => 중복 조합
-
6개 세트에서 마진이 좋은 상품도, 나쁜 상품도 있음
-
마진의 기준 0.13
-
6개 상품의 마진이 0.13인 상품갯수의 확률변수 X = {0,1,2,3,4,5,6}
-
이때의 확률변수의 분포
# 이벤트 상품 목록 구하기 - 2000
eventlist <- c("구카카콜 250미리리터(캔)", "세계콘 170미리리터",
"딸기속우유 310미리리터(팩)", "조르지아오리지널 240미리리터(캔)",
"육개장사발탕면 86g(컵)", "카페라떼와일드 200미리리터(컵)",
"핫개컨디션파워 100미리리터(병)", "비타528 100미리리터(병)")
# 세트판매 데이터 불러오기
event <- read.csv("r-ggagi-data/example_eventsale.csv", header=F)
event <- as.list(event) # 리스트 1개당 1세트로 처리
event <- lapply(event, as.character)
head(event,3)
- $V1
-
- '비타528 100미리리터(병)'
- '세계콘 170미리리터'
- '비타528 100미리리터(병)'
- '카페라떼와일드 200미리리터(컵)'
- '조르지아오리지널 240미리리터(캔)'
- '구카카콜 250미리리터(캔)'
- $V2
-
- '구카카콜 250미리리터(캔)'
- '딸기속우유 310미리리터(팩)'
- '핫개컨디션파워 100미리리터(병)'
- '딸기속우유 310미리리터(팩)'
- '육개장사발탕면 86g(컵)'
- '카페라떼와일드 200미리리터(컵)'
- $V3
-
- '구카카콜 250미리리터(캔)'
- '카페라떼와일드 200미리리터(컵)'
- '딸기속우유 310미리리터(팩)'
- '구카카콜 250미리리터(캔)'
- '비타528 100미리리터(병)'
- '딸기속우유 310미리리터(팩)'
length(event)
2000
# 마진율 가저오기
# 데이터 적재
library(data.table)
DF <- fread("r-ggagi-data/example_conveniencestore.csv", encoding="UTF-8", data.table=F)
# 1000개 샘플링
S <- DF[sample(nrow(DF), 1000), ]
library(dplyr)
Warning message:
"package 'dplyr' was built under R version 4.0.2"
Attaching package: 'dplyr'
The following objects are masked from 'package:data.table':
between, first, last
The following objects are masked from 'package:stats':
filter, lag
The following objects are masked from 'package:base':
intersect, setdiff, setequal, union
# 상품별 요약
S2 <- S %>% filter(sellproduct == eventlist[1] | sellproduct == eventlist[2] |
sellproduct == eventlist[3] | sellproduct == eventlist[4] | sellproduct == eventlist[5] |
sellproduct == eventlist[6] | sellproduct == eventlist[7] |
sellproduct == eventlist[8] ) %>%
group_by(sellproduct) %>%
summarise(margin=min(margin)) %>% # 상품별 마진은 동일 max()도 동일
mutate(marginTF=ifelse(margin > 0.13, 1, 0))
S2
`summarise()` ungrouping output (override with `.groups` argument)
sellproduct | margin | marginTF |
---|---|---|
<chr> | <dbl> | <dbl> |
구카카콜 250미리리터(캔) | 0.10 | 0 |
딸기속우유 310미리리터(팩) | 0.11 | 0 |
비타528 100미리리터(병) | 0.20 | 1 |
세계콘 170미리리터 | 0.15 | 1 |
육개장사발탕면 86g(컵) | 0.28 | 1 |
조르지아오리지널 240미리리터(캔) | 0.27 | 1 |
카페라떼와일드 200미리리터(컵) | 0.23 | 1 |
핫개컨디션파워 100미리리터(병) | 0.30 | 1 |
install.packages('gtools')
package 'gtools' successfully unpacked and MD5 sums checked
The downloaded binary packages are in
C:\Users\205\AppData\Local\Temp\RtmpwVhmbA\downloaded_packages
library(gtools)
# 경우의 수 만들기 8개중 6개, 중복 가능
com <- combinations(length(eventlist), 6, eventlist, repeats.allowed = T)
nrow(com)
1716
head(com, 3) # 판매되는 경우의 수
head(event, 3) # 판매된 데이터
구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) |
구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 딸기속우유 310미리리터(팩) |
구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 비타528 100미리리터(병) |
- $V1
-
- '비타528 100미리리터(병)'
- '세계콘 170미리리터'
- '비타528 100미리리터(병)'
- '카페라떼와일드 200미리리터(컵)'
- '조르지아오리지널 240미리리터(캔)'
- '구카카콜 250미리리터(캔)'
- $V2
-
- '구카카콜 250미리리터(캔)'
- '딸기속우유 310미리리터(팩)'
- '핫개컨디션파워 100미리리터(병)'
- '딸기속우유 310미리리터(팩)'
- '육개장사발탕면 86g(컵)'
- '카페라떼와일드 200미리리터(컵)'
- $V3
-
- '구카카콜 250미리리터(캔)'
- '카페라떼와일드 200미리리터(컵)'
- '딸기속우유 310미리리터(팩)'
- '구카카콜 250미리리터(캔)'
- '비타528 100미리리터(병)'
- '딸기속우유 310미리리터(팩)'
c <- NULL;
for(j in 1:length(event)){ # 자료형 리스트
for(i in 1:nrow(com)){ # 자료형 데이터프레임
if(all(event[[j]] %in% com[i, ])){
c <- c(c, i)
break()
}
}
}
head(c, 10)
- 236
- 193
- 48
- 54
- 158
- 236
- 1088
- 246
- 310
- 491
# 각 eventlist의 marginTF 값 적용
com2 <- com
for(i in 1:length(eventlist)){
com2[com == eventlist[i]] <- S2[S2$sellproduct == eventlist[i],]$marginTF
}
com3 <- apply(com2, 2, as.integer) # 1 : 행(row) 단위 , 2 = 열(컬럼)단위
head(com, 3)
head(com[com == eventlist[1]])
head(com2[com == eventlist[1]])
구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) |
구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 딸기속우유 310미리리터(팩) |
구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 구카카콜 250미리리터(캔) | 비타528 100미리리터(병) |
- '구카카콜 250미리리터(캔)'
- '구카카콜 250미리리터(캔)'
- '구카카콜 250미리리터(캔)'
- '구카카콜 250미리리터(캔)'
- '구카카콜 250미리리터(캔)'
- '구카카콜 250미리리터(캔)'
- '0'
- '0'
- '0'
- '0'
- '0'
- '0'
# 구하는 확률변수 => 사건마다 마진이 있는 상품의 갯수 X = {0, 1, 2, 3, 4, 5, 6}
rv <- rowSums(com3) # 행의 값 더하기
head(rv)
- 0
- 0
- 1
- 1
- 1
- 1
# 확률변수 마다 실제 판매된 제품 넣어서 도수 구하기
rv_table <- table(rv[c])
rv_table
0 1 2 3 4 5 6
2 26 302 840 682 142 6
addmargins(rv_table, margin = 1)
0 1 2 3 4 5 6 Sum
2 26 302 840 682 142 6 2000
# 상대적 판매 비율 => 확률
rv_prop_table <- prop.table(rv_table)
rv_prop_table
0 1 2 3 4 5 6
0.001 0.013 0.151 0.420 0.341 0.071 0.003
# 시각화
library(ggplot2)
library(ggthemes)
rv_df <- as.data.frame(rv_table)
rv_df
Var1 | Freq |
---|---|
<fct> | <int> |
0 | 2 |
1 | 26 |
2 | 302 |
3 | 840 |
4 | 682 |
5 | 142 |
6 | 6 |
ggplot(rv_df, aes(x=factor(Var1), y=Freq, fill=Var1))+
geom_bar(stat='identity')
게임데이터 기하분포로 분석하기 - 기하분포
-
기하분포 : K번째 성공할 확률 분포
-
게임밸런스 조절등에 사용
library(data.table)
# 데이터 로드
DF <- fread('r-ggagi-data/example_gamedata.csv', data.table = T)
head(DF, 1)
Date2 | memberID | stage | success |
---|---|---|---|
<chr> | <int> | <chr> | <lgl> |
2015-02-15 00:00:00 | 376966 | stage_01 | TRUE |
# memberID 376966 자세히 보기
library(dplyr)
DF2 <- as_tibble(DF)
DF2 %>% filter(memberID==376966)
Date2 | memberID | stage | success |
---|---|---|---|
<chr> | <int> | <chr> | <lgl> |
2015-02-15 00:00:00 | 376966 | stage_01 | TRUE |
2015-02-17 19:55:05 | 376966 | stage_02 | FALSE |
2015-02-23 16:22:43 | 376966 | stage_02 | TRUE |
2015-02-27 17:45:02 | 376966 | stage_03 | FALSE |
2015-03-02 16:35:11 | 376966 | stage_03 | FALSE |
2015-03-14 01:03:07 | 376966 | stage_03 | TRUE |
2015-03-15 02:27:46 | 376966 | stage_04 | FALSE |
2015-03-16 20:56:15 | 376966 | stage_04 | FALSE |
2015-03-21 20:43:40 | 376966 | stage_04 | FALSE |
2015-03-27 20:39:32 | 376966 | stage_04 | FALSE |
2015-04-01 18:05:47 | 376966 | stage_04 | FALSE |
2015-04-02 11:42:09 | 376966 | stage_04 | FALSE |
2015-04-06 15:38:38 | 376966 | stage_04 | TRUE |
2015-04-06 18:40:32 | 376966 | stage_05 | FALSE |
2015-04-13 20:51:45 | 376966 | stage_05 | FALSE |
2015-04-14 12:03:54 | 376966 | stage_05 | FALSE |
2015-04-18 22:34:56 | 376966 | stage_05 | FALSE |
2015-04-23 14:52:28 | 376966 | stage_05 | FALSE |
2015-04-29 02:17:15 | 376966 | stage_05 | FALSE |
2015-05-01 02:44:45 | 376966 | stage_05 | FALSE |
2015-05-08 18:02:48 | 376966 | stage_05 | FALSE |
2015-05-11 21:11:03 | 376966 | stage_05 | FALSE |
2015-05-12 19:17:20 | 376966 | stage_05 | FALSE |
2015-05-18 17:41:19 | 376966 | stage_05 | FALSE |
2015-05-23 13:18:11 | 376966 | stage_05 | FALSE |
2015-05-27 02:47:06 | 376966 | stage_05 | FALSE |
2015-05-28 17:28:18 | 376966 | stage_05 | FALSE |
2015-05-29 18:36:09 | 376966 | stage_05 | TRUE |
2015-06-02 15:58:40 | 376966 | stage_06 | FALSE |
2015-06-04 11:10:49 | 376966 | stage_06 | FALSE |
⋮ | ⋮ | ⋮ | ⋮ |
2015-08-27 18:17:13 | 376966 | stage_07 | FALSE |
2015-09-04 15:43:18 | 376966 | stage_07 | FALSE |
2015-09-06 00:10:19 | 376966 | stage_07 | FALSE |
2015-09-08 22:36:30 | 376966 | stage_07 | FALSE |
2015-09-12 15:53:02 | 376966 | stage_07 | FALSE |
2015-09-22 20:29:17 | 376966 | stage_07 | FALSE |
2015-10-08 23:02:45 | 376966 | stage_07 | FALSE |
2015-10-11 20:47:07 | 376966 | stage_07 | FALSE |
2015-10-11 22:42:49 | 376966 | stage_07 | FALSE |
2015-10-13 01:53:08 | 376966 | stage_07 | FALSE |
2015-11-01 18:54:00 | 376966 | stage_07 | FALSE |
2015-11-02 20:48:09 | 376966 | stage_07 | TRUE |
2015-11-08 05:26:15 | 376966 | stage_08 | FALSE |
2015-11-08 22:04:22 | 376966 | stage_08 | FALSE |
2015-11-10 18:28:01 | 376966 | stage_08 | FALSE |
2015-11-14 10:30:45 | 376966 | stage_08 | FALSE |
2015-11-16 01:46:49 | 376966 | stage_08 | FALSE |
2015-11-20 14:14:02 | 376966 | stage_08 | FALSE |
2015-11-22 10:46:00 | 376966 | stage_08 | FALSE |
2015-11-22 21:58:43 | 376966 | stage_08 | FALSE |
2015-11-23 15:17:33 | 376966 | stage_08 | FALSE |
2015-11-24 00:46:42 | 376966 | stage_08 | FALSE |
2015-11-30 08:21:37 | 376966 | stage_08 | FALSE |
2015-12-01 08:04:59 | 376966 | stage_08 | FALSE |
2015-12-07 11:41:08 | 376966 | stage_08 | FALSE |
2015-12-07 20:15:47 | 376966 | stage_08 | FALSE |
2015-12-11 06:22:44 | 376966 | stage_08 | FALSE |
2015-12-27 22:17:13 | 376966 | stage_08 | FALSE |
2015-12-28 15:53:05 | 376966 | stage_08 | TRUE |
2015-12-31 13:10:58 | 376966 | stage_08 | TRUE |
# memberID 376966 stage 별 성공, 실패
DF2 %>%
filter(memberID == 376966) %>%
group_by(stage, success) %>%
select(success) %>%
summarise(count = n())
Adding missing grouping variables: `stage`
`summarise()` regrouping output by 'stage' (override with `.groups` argument)
stage | success | count |
---|---|---|
<chr> | <lgl> | <int> |
stage_01 | TRUE | 1 |
stage_02 | FALSE | 1 |
stage_02 | TRUE | 1 |
stage_03 | FALSE | 2 |
stage_03 | TRUE | 1 |
stage_04 | FALSE | 6 |
stage_04 | TRUE | 1 |
stage_05 | FALSE | 14 |
stage_05 | TRUE | 1 |
stage_06 | FALSE | 13 |
stage_06 | TRUE | 3 |
stage_07 | FALSE | 16 |
stage_07 | TRUE | 1 |
stage_08 | FALSE | 16 |
stage_08 | TRUE | 2 |
# 모든 사람들의 성공, 실패 구하기
SF <- DF2 %>%
group_by(stage, success) %>%
summarise(count = n())
SF
`summarise()` regrouping output by 'stage' (override with `.groups` argument)
stage | success | count |
---|---|---|
<chr> | <lgl> | <int> |
stage_01 | FALSE | 60 |
stage_01 | TRUE | 500007 |
stage_02 | FALSE | 503610 |
stage_02 | TRUE | 500858 |
stage_03 | FALSE | 1071222 |
stage_03 | TRUE | 521440 |
stage_04 | FALSE | 2051331 |
stage_04 | TRUE | 721099 |
stage_05 | FALSE | 4263240 |
stage_05 | TRUE | 897753 |
stage_06 | FALSE | 6020643 |
stage_06 | TRUE | 1426092 |
stage_07 | FALSE | 7945384 |
stage_07 | TRUE | 515538 |
stage_08 | FALSE | 7999460 |
stage_08 | TRUE | 999984 |
# 시각화
library(ggplot2)
library(ggthemes)
ggplot(SF, aes(x=factor(stage), y=count, colour=success, group=success))+
geom_line(size=0.7) +
geom_point(size=4) +
ggtitle('A사의 B게임 스테이지별 성공여부 그래프') +
theme_wsj()
# 성공한 횟수만 따로 저장
SF2 <- SF %>% filter(success == T)
SF2
stage | success | count |
---|---|---|
<chr> | <lgl> | <int> |
stage_01 | TRUE | 500007 |
stage_02 | TRUE | 500858 |
stage_03 | TRUE | 521440 |
stage_04 | TRUE | 721099 |
stage_05 | TRUE | 897753 |
stage_06 | TRUE | 1426092 |
stage_07 | TRUE | 515538 |
stage_08 | TRUE | 999984 |
# 스테이지별 전체 횟수 구하기
SFT <- DF2 %>% group_by(stage) %>% summarise(total =n())
SFT
`summarise()` ungrouping output (override with `.groups` argument)
stage | total |
---|---|
<chr> | <int> |
stage_01 | 500067 |
stage_02 | 1004468 |
stage_03 | 1592662 |
stage_04 | 2772430 |
stage_05 | 5160993 |
stage_06 | 7446735 |
stage_07 | 8460922 |
stage_08 | 8999444 |
# 성공 횟수와 전체 횟수를 합치기
SF3 <- cbind(SF2, total = SFT$total)
SF3
stage | success | count | total |
---|---|---|---|
<chr> | <lgl> | <int> | <int> |
stage_01 | TRUE | 500007 | 500067 |
stage_02 | TRUE | 500858 | 1004468 |
stage_03 | TRUE | 521440 | 1592662 |
stage_04 | TRUE | 721099 | 2772430 |
stage_05 | TRUE | 897753 | 5160993 |
stage_06 | TRUE | 1426092 | 7446735 |
stage_07 | TRUE | 515538 | 8460922 |
stage_08 | TRUE | 999984 | 8999444 |
# 스테이지마다 시도횟수 , 성공횟수 => 성공비율 구하기
SF4 <- SF3 %>% mutate(p = count/total)
SF4
stage | success | count | total | p |
---|---|---|---|---|
<chr> | <lgl> | <int> | <int> | <dbl> |
stage_01 | TRUE | 500007 | 500067 | 0.99988002 |
stage_02 | TRUE | 500858 | 1004468 | 0.49863012 |
stage_03 | TRUE | 521440 | 1592662 | 0.32740155 |
stage_04 | TRUE | 721099 | 2772430 | 0.26009638 |
stage_05 | TRUE | 897753 | 5160993 | 0.17394966 |
stage_06 | TRUE | 1426092 | 7446735 | 0.19150567 |
stage_07 | TRUE | 515538 | 8460922 | 0.06093166 |
stage_08 | TRUE | 999984 | 8999444 | 0.11111620 |
베르누이 시행 확인 => 이항분포, 기하분포
-
성공/ 실패
-
스테이지마다 같은 밸런스 => 성공확률 동일
-
누군가 성공이 다른 사람에게 영향 없음 => 독립
-
게임의 특성 상 기하분포 적용
-
n 번째에 스테이지를 성공할 확률은?
-
이번 스테이지는 5번만에 90% 유저가 성공하도록 하기
# stage_03 일 때 기하분포
x <- 1:15
y <- dgeom(x, 0.327)
plot(x, y, type='h')
# 기하분포 값을 자세히
round(y, 3)
- 0.22
- 0.148
- 0.1
- 0.067
- 0.045
- 0.03
- 0.02
- 0.014
- 0.009
- 0.006
- 0.004
- 0.003
- 0.002
- 0.001
- 0.001
# 1번 실패 후 성공(첫번째 값) p(1-p)^k-1
0.327*(1-0.327)
0.220071
#누적 기하분포 확률값
pgeom(5, 0.327) # 실실실실성
pgeom(4, 0.327) # 실실실성
0.907084025666639
0.861937631005407
# 6번 실패 하고 성공할 확률 90% 만들기
# 0.9가 될때가 p값 구하는 함수 만들기
findp <- function(n, p){
for(i in 1:99){
a <- pgeom(n, 0.01*i)
if(a > p){
print(paste0('n값이 ',n,'일 때'))
print(paste0('p값 ',0.01*i,'을 사용하면'))
print(paste0('확률 ',a,'이 나옵니다'))
break()
}
}
}
# 6번만에 90%가 성공하는 p값 => 게임밸런스를 0.327에서 0.29
findp(6, 0.9)
[1] "n값이 6일 때"
[1] "p값 0.29을 사용하면"
[1] "확률 0.90904879841609이 나옵니다"