【R分享|实战】一次有趣的尝试~函数定义与循环
#### 集五福 ####
## 老马手里有爱国、和谐、富强、友善、敬业五种卡。
## 假设每张卡上出现以上五种卡的可能性相同,并且可以无限次收集(放回)。
## 集齐五福卡需要收集的卡片数?
rm(list = ls())#清空当前环境
## 定义一个函数来判断向量中独有种类的数量
count_unique <- function(x) { #自定义函数,{} 中括号中的为函数体
library(tidyverse) #加载该包是为了运行%>%管道符号
x %>% #%>% 该符号的理解可以解读成然后
#也就是这里的解读为输入x向量,然后进行下一步
unique() %>% #unique() 主要判断x向量中不同种类的唯一数量
length() #向量长度
}
## 设置种子数
set.seed(1111) #由于代码中存在随机生成的结果,设置种子目的是保证每次输出结果一致。
## 求抽取5种卡的卡片数(即求迭代次数)
times <- 0 #初始数值
#while循环常用来计算迭代次数和一些数值的计算
while(times >= 0){ #while() 括号中的为条件,当满足这个条件时,进行{}中括号的内容
times = times + 1 #第二行是我们要求得次数 每次当n大于等于0时,则times+1
#这也意味着如果没有满足后面if的条件,times会一直循环下去,直到满足条件输出结果
df = sample(c("爱国","友善","富强","和谐","敬业"), times, replace = T)
#sample随机抽样函数/n抽样次数/replace有放回的抽样 没有设置pro表示默认抽取情况的概率相等
if(count_unique(df)==5){ #在while循环中套用if条件的循环
#我们利用上面定义的函数,来判断是否满足我们的条件
#条件解读为:当五福均至少抽取一次,也就是自定义函数count_unique()为5时,
#执行中括号中的函数体
print(times) #输出迭代次数,也就是需要的卡片数
break() #当满足if条件时,break作出停止循环的命令
}
}
## 其实我们可以看出来当概率相等的时候,可能10张以内咱们就能集齐(可以更换种子数去验证结果)
## 当卡片概率不等的时候,敬业福概率只有亿分之一时,看看什么叫绝望
times <- 0
while(times >= 0){
times = times + 1
df = sample(c("爱国","友善","富强","和谐","敬业"), times, replace = T,
prob = c(0.3,0.2,0.2,0.299999999,0.000000001))
if(count_unique(df)==5){
print(times)
break
}
}
## 经过师兄最后的建议,可以用自定义函数来打包循环,可以做到重复使用
count_times <- function(x){
times <- 0
while(times >= 0){
times = times + 1
df = sample(x, times, replace = T) #抽样的向量可以自行设置
if(count_unique(df)==5){
print(times)
break
}
}
}
## 这里我们用五福和5个字母来验证一下
x <- c("爱国","友善","富强","和谐","敬业")
y <- c("A","B","C","D","E")
set.seed(1111)
count_times(x)
set.seed(1111)
count_times(y)
#结果相同,验证无误
用R markdown输出结果: