以创建体重函数为例:BMI=Weight/Height^2
> BMI<-function(Weight,Height){
+ bmi<-Weight/Height^2
+ names(bmi)<-"BMI"
+ return(bmi)
+ }
为了给该列表的各个元素命名,你可以使用如下的代码:
> BMI<-function(weight,height){
+ bmi<-weight/height^2
+ res<-list(Weight=weight,Height=height,BMI=bmi)
+ return(res)
+ }
> BMI(60,1.62)
$Weight
[1] 60
$Height
[1] 1.62
$BMI
[1] 22.86237
现在假设我们想要计算多个个体的BMI。比如John和peter的:
> john<-c(74,1.90)
> peter<-c(70,1.82)
> mydata<-rbind(john,peter)
> for(i in 1:2){
+ print(BMI(mydata[i,1],mydata[i,2]))
+ }
$Weight
john
74
$Height
john
1.9
$BMI
john
20.49861
$Weight
peter
70
$Height
peter
1.82
$BMI
peter
21.13271
接下来这段代码用一个实例来说明具有默认值的参变量以及能处理一些错误的函数stop()的用法。
> BMI<-function(weight,height,height.unit="m"){
+ if(length(weight) !=length(height))
+ stop("the vectors weight and height must have the same length.")
+ if(height.unit == "cm")height<-height/100
+ bmi<-weight/height^2
+ res<-list(Weight=weight,Height=height,BMI=bmi)
+ return(res)
+ }
> BMI(70,1.82)
$Weight
[1] 70
$Height
[1] 1.82
$BMI
[1] 21.13271
补充函数用法:(1)length函数:length(x),表示一个向量的长度。
(2)stop()函数:停止运行下一步。
当然,使用函数stop()肯会带来一些苦恼,例如,在一项模拟研究中,人们常需要反复地调用某个函数。如果在某一次调用中
该函数返回了一个错误,则整个模拟就会停止。明智的做法是使用函数try():如果函数遇到了一个错误,相关的错误信息将会被储存在一个对象中但不会停止模拟的运行。
>set.seed(123)
#set.seed()用于设定随机数种子,一个特定的种子可以产
#生一个特定的伪随机序列,这个函数的主要目的,是让你的模拟能够可重复出现,
#因为很多时候我们需要取随机数,但这段代码再跑一次的时候,结果就不一样了
#,如果需要重复出现同样的模拟结果的话,就可以用set.seed()。在这里我们就
#是让下面的结果可以重复出现123次,而不是每次的值都不一样
>x<-rnorm(50)
#rnorm(n, mean = 0, sd = 1)产生n个服从正态分布的随机数
>doit<-function(x){
x<-sample(x,replace=TRUE)
#sample(x, size, replace = FALSE, prob = NULL) sample是随机抽样函数,
#x表示进行随机抽样的对象,size表示抽样的样本数,replace=T表示放回抽样,即可
#重复抽样。
if(length(unique(x))>30) mean(x)
else{stop("too few unique points")}
}
res<-lapply(1:100,function(i) try(doit(x),TRUE))
#lapply(X, FUN, ...)
#lapply函数
#可以循环处理列表中的每一个元素
#lapply(参数):lapply(列表,函数/函数名,其他参数)
#总是返回一个列表
根据个体的BMI值就可以将他们划分为不同的体重类别或等级,BMI与体重类别之间的对应关系如下表所示:
严重体重过轻 | 体重过轻 | 正常体重 | 超 重 | 中度肥胖 | 严重肥胖 | 病态肥胖 |
【15,16.5) | [16.5,18.5) | 【18.5,25) | 【25,30) | 【30,35) | 【35,40) | 【40,41)
|
下面的函数将根据用户的BMI值输出他们的体重类别。
>BMI<-function(Weight,Height){
+ bmi<-Weight/Height^2
+ names(bmi)<-"BMI"
+ return(bmi)
+ }
>weight.category<-function(bmi){
if(bmi<16.5) category<-"severely underweight"
else{
if(bmi<18.5) category<-"underweight"
else{
if(bmi<25) category<-"normal weight"
else{
if(bmi<30) category<-"overweight"
else{
if(bmi<35) category<-"moderate obesity"
else{
if(bmi<40) category<-"severe obesity"
else{
if(bmi<41) category<-"morbid obesity"}}}}}}
cat(paste("your BMI is: ",category,".\n",sep=""))}
#cat( ... , file = "", sep = " ", fill = FALSE, labels = NULL,append = FALSE)
#file:一个文件链接或文件名,若不写则表示输出到控制台;
#sep:分隔符
#append:是否追加,当且晋档参数file是文件名而非链接时,此参数才有效
————————————————
补充:paste(),cat()函数的区别
从下面的例子中可以清晰的了解cat函数与paste函数的区别.
> paste(1:9,c("st","nd","rd",rep("th",6)),sep="",collapse=",")
[1] "1st,2nd,3rd,4th,5th,6th,7th,8th,9th"
> cat(1:9,c("st","nd","rd",rep("th",6)),sep="")
123456789stndrdthththththth
函数weight.category()的代码可以用函数switch()来简化。
>BMI<-function(Weight,Height){
+ bmi<-Weight/Height^2
+ names(bmi)<-"BMI"
+ return(bmi)
+ }
>weight.category<-function(bmi){
intervals.BMI<-c(15,16.5,18.5,25,30,35,40,41)
code<-as.character(rank(c(bmi,intervals.BMI),
ties.method="max")[1])
category<-switch(code,"2"="severely underweight",
"3"="underweight" "4"="normal weight","5"="overweight",
"6"="moderate obesity","7"="severely obesity","8"="morbid obesity")
cat(paste("your BMI is:",round(bmi,3),"this corresponds to weight category:",category,sep=""))
}
weight.category(BMI(70,1.82)$BMI)
your BMI is:21.133.
this corresponds to weight category:normal weight.
##rank(x, na.last = TRUE,
ties.method = c("average", "first", "random", "max", "min"))
#(1) rank 函数是对一维度数组、向量x 进行排序。若x 为数值,则按照小数在线大数在后的原则进行排序,#若x 为因子,则应参考[说明1]进行顺序因子设计。
#P.S. 实际情况中,存在大量用二维表格描述的数据,比如行表示地点列表示时间的统计表,若进行排序,应##先通过字符拼接的手段将表格转化为一维的向量,否则结果将失去意义。
#(2) rank 将数据分为确定值与缺失值两种。缺失值可按先后排在确定值之间(na.last = FALSE), 也可排在#之后(na.last = TRUE), 也可保留,不参与排序(na.last = "keep").
#(3) "first" 是最基本的排序,小数在前大数在后,相同元素先者在前后者在后。
"max" 是相同元素都取该组中最好的水平,即通常所讲的并列排序。
"min" 是相同元素都取该组中最差的水平,可以增大序列的等级差异。
"average" 是相同元素都取该组中的平均水平,该水平可能是个小数。
"random" 是相同元素随机编排次序,避免了“先到先得”,“权重”优于“先后顺序”的机制增大了随机的程度。
##
#switch(expr, list)
#其中,expr为表达式,其值或为一个整数值或为一个字符串;list为一个列表。
#运行机理:若expr的计算结果为整数,且值在1~length(list)之间时,则switch()函数返回列表相应位置的#值。若expr的值超出范围,则没有返回值(老版本的R中返回NULL)。
#ex:
> x<-2
> switch(x,"yangfan","obama","trump")
[1] "obama"
可是,当这个函数用于一个向量时会输出一个错误的结果
> weight.category(BMI(c(70,74),c(1.82,1.90))$BMI)
your BMI is:21.133.
this corresponds to weight category:overweight.
your BMI is:20.499.
this corresponds to weight category:overweight.
我们可以对这个函数做一些改变使他能同时对几个个体进行计算,注意保留字NULL,和函数is.null()的使用(他们能敏锐的处理参变量names)
> BMI<-function(weight,height){
+ bmi<-weight/height^2
+ res<-list(Weight=weight,Height=height,BMI=bmi)
+ return(res)
+ }
> weight.category<-function(bmi,names=NULL){
+ intervals.BMI<-c(15,16.5,18.5,25,30,35,40,41)
+ n<-length(bmi)
+ if(is.null(names)) names<-paste("subject number",1:n)
+ if(length(names)!=n)stop(paste("the vector of'names'must
be of the length",n))
+ code<-vector("integer",length=n)
+ category<-vector("character",length=n)
+ for(i in 1:n){
+ code[i]<-as.character(rank(c(bmi[i],intervals.BMI),
ties.method = "max")[1])
+ category[i]<-switch(code[i],"2"="severely underweight","3"="underweight","4"="normal weight","5"="overweight",
"6"="moderate obesity","7"="severely obesity","8"="morbid obesity")
+ cat(paste(names[i],"your BMI is:",round(bmi[i],3)," this
corresponds to weight category:",category[i],sep="")) }}
> weight.category(BMI(c(70,74),c(1.82,1.90))$BMI)
subject number 1your BMI is:21.133 this corresponds to
weight category:normal weightsubject number 2your BMI
is:20.499 this corresponds to weight category:normal weight