본문 바로가기

확률론(in R)

확률론2-2 : 코딩을 활용한 확률계산[in r]

# 3####
# 파란 공 3개, 빨간 공 7개, 노란 공 4개, 녹색 공 6개가 
# 들어 있는 바구니에서 공을 여섯개를 뽑을 때[컨비네이션]
# 표본공간
basket<-c(rep("B",3),rep("R",7),rep("Y",4),rep("G",6))
omega3<-combn(x = basket,m = 6) %>% data.frame()

 

combn 함수를 이용한 경우의 수.20C3

그런데 combn함수는 행렬로 뱉어주고 위에는 데이터프레임으로 변환하였으나, 열로 데이터를 나타내준다.

우리가 알고 있는 폼으로 변환하기 위해 전치를 시켜주자.

omega3<-combn(x = basket,m = 6) %>% t %>% data.frame()

위의 데이터프레임을 Transpose한 결과.

> # 색깔별로 공의 개수를 세는 함수
> # 이것도 세는데 문자형이므로, 계산이 안된다. 함수를 이용하자!
> countB <- function(x) sum(x=="B")
> countR <- function(x) sum(x=="R")
> countY <- function(x) sum(x=="Y")
> countG <- function(x) sum(x=="G")
#진리형으로 반환하므로, 카운팅은 가능하다.
> # Pr{3B,3Y} B가 3개 그리고 Y가 3개일 확률
> omega3$B <- omega3 %>% apply(1,countB)
> omega3$R <- omega3 %>% apply(1,countR)
> omega3$Y <- omega3 %>% apply(1,countY)
> omega3$G <- omega3 %>% apply(1,countG)

같은 행에 붙여버려서 문자형 카운팅 되지 않는 것을 되게 만들었다.

> paste("Pr{3B,3Y} = " , omega3 %>% filter(B==3 & Y==3) %>%nrow()/nrow(omega3)) 
[1] "Pr{3B,3Y} =  0.000103199174406605"
> # Pr{3R,3G}
> paste("Pr{3R,3G} = " , omega3 %>% filter(R==3 & G==3) %>%nrow()/nrow(omega3)) 
[1] "Pr{3R,3G} =  0.0180598555211558"
> # Pr{2B,1R,2Y,1G}
> paste("Pr{2B,1R,2Y,1G} = " , omega3 %>% filter(B==2 & R==1 & Y==2 & G==1) %>%nrow()/nrow(omega3)) 
[1] "Pr{2B,1R,2Y,1G} =  0.0195046439628483"
> # 4 ####
> # 네 종류의 무늬에 1번부터 13번까지 표기된 52장의 카드덱
> ##Ace=1,Jack=11,Queen=12,King=13
> # 카드 2, 3, 4장을 뽑을 때 표본공간
> card <- c(paste0("C",1:13),paste0("D",1:13),
+           paste0("H",1:13),paste0("S",1:13))
> card
 [1] "C1"  "C2"  "C3"  "C4"  "C5"  "C6"  "C7"  "C8"  "C9"  "C10" "C11"
[12] "C12" "C13" "D1"  "D2"  "D3"  "D4"  "D5"  "D6"  "D7"  "D8"  "D9" 
[23] "D10" "D11" "D12" "D13" "H1"  "H2"  "H3"  "H4"  "H5"  "H6"  "H7" 
[34] "H8"  "H9"  "H10" "H11" "H12" "H13" "S1"  "S2"  "S3"  "S4"  "S5" 
[45] "S6"  "S7"  "S8"  "S9"  "S10" "S11" "S12" "S13"

#번외)

어떻게 paste0를 사용해서 이렇게 되는가? 기본적으로 paste0는 공백없이 하나로 묶어주는 역할을 한다.

> paste0(1,2,3,4)
[1] "1234"
> paste0(1,2,3,4) %>% length()
[1] 1

> paste0(c(rep("card",7)))
[1] "card" "card" "card" "card" "card" "card" "card"
> paste0(c(rep("card",7))) %>% length()
[1] 7

하지만, 벡터형식으로 묶인 형태에서는 각 원소를 개인 취급한다.

그렇기에 개수도 원소개수만큼 카운팅된다.

그렇다면 paste(원소1,원소2,원소3,...,c(a,b,c,..))는 어떻게 될까? 분배법칙을 아는가?

> paste("빵은","역시","페스츄리",c("와 아아","와 바닐라라떼","와 헤이즐넛"))
[1] "빵은 역시 페스츄리 와 아아"       "빵은 역시 페스츄리 와 바닐라라떼"
[3] "빵은 역시 페스츄리 와 헤이즐넛"

원소들은 고정되며, 벡터들이 분배되는 모습을 보인다.

여기서 이미 위의 paste0("C",1:13)의 궁금증을 해결 할 수 있다. 하지만 더 나아가서 paste(벡터,벡터)형식;

paste(c(a,b,c),c(d,e,f))같은 형식은 어떻게 될까?

> paste(c("빵은","라면은","커피는"),c("페스츄리","신라면","아아"))
[1] "빵은 페스츄리" "라면은 신라면" "커피는 아아"

서로서로 그 같은 위치에 있는 것과 매칭되는 것으로 볼 수 있다. 또, 여기서 양 벡터길이가 다르다면?

> paste(c("빵은","라면은","아이스 커피는","바삭한"),c("페스츄리","신라면","아아"))
[1] "빵은 페스츄리"      "라면은 신라면"      "아이스 커피는 아아"
[4] "바삭한 페스츄리"

흔히 R에서 사용되는 리사이클링 현상이 나타난다. 짧은 쪽이 리사이클링 된다.

 

이제 다시 문제로 넘어가자.

# 카드 2, 3, 4장을 뽑을 때 표본공간
CD2<-card %>% combn(,m = 2) %>% t %>%  data.frame()
CD3<-card %>% combn(,m = 3) %>% t %>%  data.frame()
CD4<-card %>% combn(,m = 4) %>% t %>%  data.frame()
#CD4의 Sample space가 20만개가 넘어가므로 계산이 좀 걸릴 수 있다.
# 같은무늬인지 판별하는 함수, 
#앞글자를 따서 이용하면 되겠다![단어 추출]
#유일한 관측치를 사용.[unique]
#Ex) substr(c("C1","D1","D2","S1","D3"),start = 1,stop = 1) %>% unique()
same_shape <- function(x) (substr(x,start = 1,stop = 1) %>% unique() %>% length()) ==1

같은무늬인지 확인할려면 우선,

1.표본점(Sample point)의 앞글자가 주요사항임을 체크한다.

2.체크하는데 있어서 위의 예시로 "C","D","D","S,"D"라고 나올 것인데, 다른 모양이 한개라도 나오면 F, 중복도 안되면 무조건 체크할때 "C" or "D" or "H" or "S" 이런 식으로 하나의 결과만으로 나타낼 수 있다. 그럼 개수를 1개이면 T로 나타내면 된다.

3.중복을 제거하기 위해 유니크함수를 이용하면 유일한 관측치만 나타낼 수 있다.

> substr(c("C1","D1","D2","S1","D3"),start = 1,stop = 1) %>% unique()
[1] "C" "D" "S"
> same_shape(c("C1","D1","D2","S1","D3"))
[1] FALSE
> same_shape(c("D1","D2","D3"))
[1] TRUE

 

> # 숫자가 연속되는지 판별하는 함수[연속인지 판단=>수치형]
> consecutive<-function(x){
+   v<-substr(x,start = 2,stop = 3) %>% as.numeric() %>% sort
+   v<-v[length(unique(v))==length(v)] #중복인지 판단.
+   return(max(v)-min(v) == length(v)-1)
+ }

> c("C1","H2","S3") %>% consecutive()
[1] TRUE

> # 2장의 카드를 꺼냈을 때 모두 같은 무늬가 나올 확률
> (CD2 %>% apply(1,same_shape)) %>% sum / nrow(CD2)
[1] 0.2352941
> # 3장의 카드를 꺼냈을 때 모두 같은 무늬가 나올 확률
> (CD3 %>% apply(1,same_shape)) %>% sum / nrow(CD3)
[1] 0.05176471
> # 4장의 카드를 꺼냈을 때 모두 같은 무늬가 나올 확률
> (CD4 %>% apply(1,same_shape)) %>% sum / nrow(CD4)
[1] 0.01056423

consecutive 함수를 만드는데 어려울 수 있다.

하지만 차근차근 해보면 금방 해결된다. 1에서 13중 {3,4,5,6,7}을 뽑았다고 가정하자.

이는 연속된 수이며 최대치가 7 최소치가 3이다. 서로 빼주면 4이며, 개수는 5개이다. 개수에 1개를 빼주면 4개가 된다.

하지만 이것이 우연일까? 다음과 같이 일반화 해보겠다.

연속된 수의 일반화

그렇기에 각 끝값을 빼주었을 때, 전체개수보다 1개 적으면 연속된 수라고 판단하면 된다. 

> # 카드 4장을 뽑을 때
> # A : 모두 다른 무늬가 나옴
> # B : 1이 최소 한번은 나옴
> # 모두 다른무늬인지 확인하는 함수 
> diff_shame <- function(x) (substr(x,start = 1,stop = 1) %>% unique() %>% length()) ==4
> A <- CD4 %>% filter(apply(CD4,1,diff_shame))
> A %>% head()
  X1 X2 X3 X4
1 C1 D1 H1 S1
2 C1 D1 H1 S2
3 C1 D1 H1 S3
4 C1 D1 H1 S4
5 C1 D1 H1 S5
6 C1 D1 H1 S6
> onein<- function(x) {
+   v<- substr(x,2,3) %>% as.numeric()
+   return(1 %in% v) #1이 v에 있냐? 
+ }
> 
> B<- CD4 %>% filter(apply(CD4,1,onein))
> B %>% head()
  X1 X2 X3 X4
1 C1 C2 C3 C4
2 C1 C2 C3 C5
3 C1 C2 C3 C6
4 C1 C2 C3 C7
5 C1 C2 C3 C8
6 C1 C2 C3 C9
> PrA<-nrow(A)/nrow(CD4)
> PrB<-nrow(B)/nrow(CD4)
> # A와 B는 독립인가? =>Pr{A∩B}=Pr{A}∩Pr{B}
> #Pr{A∩B}
> PrAandB<- nrow(intersect(A,B))/nrow(CD4)
> PrAandB==PrA*PrB
[1] FALSE

onein은 최소1이 행벡터에 들어갈지를 나타내는 함수이다. 적당한 함수가 없어서 만든 사용자 함수이다.

그리고 A:다른 무늬가 나올 사건 , B: 1이 최소 한번 나올 사건은 독립이 아님을 알 수 있다. (두 사건이 영향을 주지 않음= 두 사건이 서로의 확률변화를 미치지 않음. )

그렇다면, 상호배반(Mutually Exclusive)일까? 

A,B가 동시에 일어날 수 없으면 상호배반이다. 하지만 다른무늬가 나오면서 1이 최소 한번 나올 수 있으므로, 이는 상호배반이 아니다.

 

-출처: AI소프트웨어학과 이두호교수님 강의파일