起初想把標(biāo)題定為“大一概率習(xí)題,難倒了10年R語(yǔ)言大佬”圈纺,雖然主題明確秦忿,但再三考慮讀者的閱讀情景,還是用這個(gè)“用R語(yǔ)言創(chuàng)建樣本空間蛾娶,計(jì)算事件發(fā)生概率”標(biāo)題吧:
1> 寫代碼著急找函數(shù)灯谣,標(biāo)題寫一些關(guān)鍵詞,易于讀者檢索茫叭;
2> 本篇重點(diǎn)在于講解題目的R編程實(shí)現(xiàn),而不是討論中西教育差異半等;
3> 不要看起來(lái)博主技術(shù)很菜揍愁。
表弟今年去英國(guó)讀書,前幾天發(fā)給我一份概率論習(xí)題杀饵,“姐莽囤,這個(gè)題教授讓拿RMarkdown實(shí)現(xiàn),求指導(dǎo)切距⌒喽校”
看到題目的那一刻,I am soooooo fang(慌)C瘴颉;靶ぁ!
這能是大一學(xué)習(xí)2個(gè)月的練習(xí)題葡幸?最筒??完全可以拿來(lái)考R專業(yè)證書好嘛N颠丁4仓!
【題目】
隨機(jī)試驗(yàn):從n+2張card中隨機(jī)抽取蔑水,1,2,3,...,n是綠牌邢锯,n+1,n+2是紅牌,取出后不放回搀别,每張牌拿到的概率相等丹擎。
1> 抽到第一張紅牌之前,所有card都放在X桌上歇父,包括第一張紅牌鸥鹉;
2> 接下來(lái)抽到的card放在Y桌上蛮穿,直到抽到第二張紅牌,第二張紅牌也放在Y桌上毁渗;
3> 剩余抽到的card放在Z桌上践磅。
下圖為當(dāng)n=4時(shí),XYZ桌上card組合的一種結(jié)果示例灸异。
【要求】
1> 使用R語(yǔ)言編程計(jì)算概率事件府适,且使用規(guī)范的數(shù)學(xué)符號(hào);
2> 假設(shè)n≥2肺樟,給出這些問題的答案:
? ? a) 定義隨機(jī)實(shí)驗(yàn)的樣本空間 Ω
? ? b) 計(jì)算樣本空間的大小 |Ω|
? ? c) 定義事件A(3張桌子上都至少有1張綠牌)檐春,定義事件B(X桌上至少有1張綠牌)
? ? d) 計(jì)算事件A、事件B發(fā)生的概率(驗(yàn)證:當(dāng)n=4時(shí)么伯,P(A)=1/5)
全網(wǎng)搜了2小時(shí)資料后疟暖,得出一個(gè)結(jié)論:這個(gè)題,“拿來(lái)主義”田柔,它不好用了俐巴!
為啥呢?硬爆?欣舵?
1> 與這個(gè)題型相似的資料非常多,但是沒有R語(yǔ)言解題的連貫邏輯缀磕;
2> 許多技術(shù)博客要付費(fèi)才能查看全文缘圈,且提及的函數(shù)不適用。
想想自己寫一個(gè)吧袜蚕。
接下來(lái)分3個(gè)部分來(lái)說(shuō)明題目的實(shí)現(xiàn)過程:
1. 解題邏輯&函數(shù)
2. Rcode示例
3. RMarkdown交作業(yè)
一糟把、解題邏輯&函數(shù)
1. 解題邏輯
假設(shè):n=4,有n+2張牌牲剃,即6張牌糊饱,1,2,3,4是綠牌,5,6是紅牌颠黎。
1> 創(chuàng)建樣本空間大矩陣Ω
矩陣Ω的行數(shù)為隨機(jī)試驗(yàn)所有可能結(jié)果的總數(shù)另锋,列數(shù)為card數(shù)量;
當(dāng)取出第一張card時(shí)有6種可能狭归,第二張有5種可能夭坪,...,第六張有1種可能过椎,也就是總共有 6*5*4*3*2*1=6! 種card排列組合結(jié)果室梅,即行數(shù)為6! ;
第1列記錄第一張card值,第2列記錄第二張card值亡鼠,以此類推赏殃,總共六張card,即列數(shù)為6间涵;
2> 查找每個(gè)事件中兩張紅牌的位置仁热;
3> 根據(jù)紅牌位置將隨機(jī)事件結(jié)果賦值給X、Y勾哩、Z抗蠢;
4> 計(jì)算每個(gè)事件中X、Y思劳、Z分別包含幾張綠牌迅矛;
5> 定義目標(biāo)事件&計(jì)算概率
圖中所示為步驟1-2-3的矩陣示例。
2. R語(yǔ)言相關(guān)函數(shù)
對(duì)于上述解題步驟潜叛,涉及到這些R語(yǔ)言操作以及函數(shù)使用:
1> 計(jì)算N的階乘:prod(1:N)
2> 生成1:N所有排列組合秽褒,調(diào)用gtools包中的函數(shù):permutations()
(注意:這里不可以使用sample()函數(shù),sample()只能用來(lái)模擬隨機(jī)事件威兜,不能生成樣本空間销斟。)
3> 字符串拼接:paste()
4> 在字符串中查找指定字符的位置,調(diào)用stringr包中的函數(shù):str_locate()
5> 字符串截饶凳簟:str_sub()
6> 計(jì)算字符串中指定字符的個(gè)數(shù):str_count()
7> 對(duì)數(shù)據(jù)框篩選指定條件的行:subset()
二票堵、 Rcode示例
【1. 創(chuàng)建樣本空間Ω】
n<-4# 定義n
N<-n+2 # card數(shù)量
cards<-1:N # 牌中包含的數(shù)字
library(gtools)
Omega<-permutations(n=N, r=N, v=cards,repeats.allowed=FALSE)# 全排列組合矩陣扼睬,不允許重復(fù)
Omega<-as.data.frame(Omega)# 矩陣轉(zhuǎn)為數(shù)據(jù)框格式
【2. 查找2張紅牌位置】
分成3段code來(lái)實(shí)現(xiàn)
# 1. 對(duì)每一行生成一個(gè)拼接字符串
for (i in 1:prod(1:N)) {
? ? ? Omega[i,N+1] <- do.call(paste,c( Omega[i,1:N],sep=''))
?}
# 2. 計(jì)算指定字符:n+1逮栅、n+2所在位置
library(stringi)
library(stringr)
n1<-as.character(n+1)
n2<-as.character(n+2)
Omega$label1<-str_locate(Omega$V7,n1)# n+1的位置
Omega$label2<-str_locate(Omega$V7,n2)# n+2的位置
# 3. 計(jì)算第一次出現(xiàn)紅牌、第二次出現(xiàn)紅牌的位置
for (i in 1:prod(1:N)) {
? Omega$label_1st_red[i]<-min(Omega$label1[i],Omega$label2[i])# 第一張紅牌的位置
? Omega$label_sec_red[i]<-max(Omega$label1[i],Omega$label2[i])# 第二張紅牌的位置
?}
【3. 將隨機(jī)事件結(jié)果賦值給X窗宇、Y措伐、Z】
# 根據(jù)紅牌位置截取字符串,生成X军俊、Y侥加、Z的數(shù)據(jù)集
Omega$table_X<-str_sub(Omega$V7,1,Omega$label_1st_red)
Omega$table_Y<-str_sub(Omega$V7,Omega$label_1st_red+1, Omega $label_sec_red)
Omega$table_Z<-str_sub(Omega$V7,Omega$label_sec_red+1,N)
【4. 計(jì)算每個(gè)事件中X、Y粪躬、Z分別包含幾張綠牌】
for (i in 1:prod(1:N)) {
? Omega$table_X_green_count[i]<-sum(str_count(Omega$table_X[i],as.character(c(1:n))))
? Omega$table_Y_green_count[i]<-sum(str_count(Omega$table_Y[i],as.character(c(1:n))))
? Omega$table_Z_green_count[i]<-sum(str_count(Omega$table_Z[i],as.character(c(1:n))))
?}
【5. 定義目標(biāo)事件&計(jì)算概率】
# 事件A:每張桌子都至少有1張綠牌
# 事件B:X桌子上至少有1張綠牌
event_A<-(Omega$table_X_green_count>=1 & Omega$table_Y_green_count>=1 & Omega$table_Z_green_count>=1)
event_B<-(Omega$table_X_green_count>=1)
# 計(jì)算事件概率
prob_event_A<-nrow(subset(Omega,event_A))/prod(1:N)
prob_event_B<-nrow(subset(Omega,event_B))/prod(1:N)
# 輸出結(jié)果
head(Omega)
print(paste0('|Ω|:',prod(1:N)))
print(paste0('P(A):',prob_event_A))
print(paste0('P(B):',prob_event_B))
三担败、RMarkdown交作業(yè)
將Rcode嵌入RMarkdown原文件的代碼框中,可以將程序結(jié)果輸出為HTML镰官、docx提前、PDF等文件,這部分對(duì)rmd文件格式做個(gè)簡(jiǎn)單介紹泳唠。
rmd代碼主要包括3個(gè)模塊:
1. 文件信息設(shè)置狈网,如:標(biāo)題、作者、輸出文件的格式拓哺;
2. 全局設(shè)置勇垛,如:是否在文件中顯示代碼部分、警告信息是否寫入結(jié)果文件士鸥;
3. Rcode部分闲孤,即代碼主體。
1. 文件信息設(shè)置
---
title: "用R語(yǔ)言創(chuàng)建樣本空間础淤,計(jì)算事件發(fā)生概率"
author: "千行"
date: "2023/11/11"
output:
? ? html_document: default
---
2. 全局設(shè)置
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)# 文件中不顯示代碼行
```
3. Rcode部分
```{r results='hold',warning=FALSE}
n<-4# 定義n
N<-n+2 # card數(shù)量
cards<-1:N # 牌中包含的數(shù)字
library(gtools)
Omega<-permutations(n=N, r=N, v=cards,repeats.allowed=FALSE)# 全排列組合矩陣崭放,不允許重復(fù)
Omega<-as.data.frame(Omega)# 矩陣轉(zhuǎn)為數(shù)據(jù)框格式
head(Omega,10)
```
把R代碼主體替換到RMarkdown的Rcode中,點(diǎn)擊Knit鸽凶,就可以交作業(yè)啦~
文末:
1> 這個(gè)題最難的部分在于樣本空間的創(chuàng)建币砂,博主真的是不知道如何快速生成全排列組合,就先用sample()模擬了一個(gè)大樣本矩陣玻侥;
2> 從邏輯到code實(shí)現(xiàn)總共用了6小時(shí)决摧,后來(lái)問了ChatGPT,它1分鐘內(nèi)給出了結(jié)果凑兰,且代碼邏輯精煉掌桩、計(jì)算過程節(jié)省內(nèi)存,最驚喜的是它檢索出了全排列組合函數(shù)permutations()姑食,幫助解決了第一步的問題波岛,真棒!
3> 當(dāng)文心一言慢悠悠走來(lái)音半,讓我覺得AI還很遠(yuǎn)的時(shí)候则拷,ChatGPT出現(xiàn)就是一道閃電。