2.5.1程序控制结构
程序控制结构是应用if条件语句、循环语句等控制程序的走向。程序控制结构又称为流程控制。条件语句包括if,swithc语句,可用复合表达式而且可用ifelse,switch语句根据条件表达式的值,选择执行的语句组。循环语句有for、while、repeat语句,并且可用组合break和next语句的方法。
一、条件语句
1.if语句
if条件语句仅在满足条件表达式时执行。条件表达式运算符(比较运算符)有>=,>,<=,<,==(是否等于),!=(不相等)。if语句的语法形式是:
if(条件表达式) expression
注意if后面的表达式的必须有小括号()。
eg1. 不妨设剑桥大学规定:若一个课程选修人数少于2人则不开设。一个专业有8个学生,他们是student=c(“亚里士多德”,”罗素”,”德谟克利特”,”恩格斯”,”柏拉图”,”希尔伯特”,”莱布尼茨”,”玻尔”),开设两门课程
class=c(“logos”,”nous”)。学生选修课程数据见下:
option=c(student,class1=c(1,1,1,1,1,1,1,1),class2=c(1,0,0,0,0,0,1,0) ),若学生所在student向量下标处的class1数据为1,则表示该学生选修课程,为0则表示不选修。则课程开设源程序是,
class=c("logos","nous")
class1=c(1,1,1,1,1,1,1,1)
class2=c(1,0,0,0,0,0,1,0)
if (sum(class1)<2) cat("class1不开设",class[1]," ")
if (sum(class2)<2) cat("class2不开设",class[2]," ")
若将nous的选修人数改成1,则有
class2=c(1,0,0,0,0,0,0,0)
c cat("class2不开设",class[2]," ")
## class2不开设 nous
if条件语句的选择结构是if-else语句,根据输入数据在条件表达式的值,选择语句执行。if-else语句有两个执行路径。语法形式:
if(cond) expression1 else expression2
注意if和else必须在同一行。或者
if(cond){
expression1
... ....
} else #不要求else紧邻“}”
expression2
注意else和expression2不能在同一行。
if-else结构的一个功能是选择表达式赋值给变量,若是复合表达式用到逻辑运算符||,&&,|;另一个功能是设置程序的多个路径。
eg2. 李四光在报考学校时,将年龄填写到姓名栏,但是报名表要用钱买,因此将十四改成李四光。
>name=c("十四")
>age=0
> age
[1] 0
> class(age)
[1] "numeric"
>if ((name=="李仲揆")&&(age==14)) schoolname="李仲揆" else name="李四光"
>name
[1] "李四光"
R语言讲究简洁,ifelse是if-else语句的紧凑方式,输出是向量。语法形式:
ifelse(cond,expression1,expression2)
eg3.报考统招和定向硕士生的年龄age在40岁以内,而委托培养和自筹经费研究生年龄不限制。
> age=33
>ugtype=ifelse(age<=40,c("统招","定向"),c("委托培养","自筹经费"))
> ugtype
[1] "统招"
2.switch语句
switch语句根据条件表达式的多个值选择一个语句执行。语法形式:
switch(cond,expression1,expression2,...,expressionn)
注意表达式间的","不能省略。switch语句输出的是根据cond选择的表达式的值。
eg4.根据班级活动中同学当时的情绪反映mood,班*应控制形势,使活动健康活泼又有秩序地进行下去。
>mood=c("sad")
> res=switch(mood,
+ pleased="I am glad you are pleased", #字符串应有双引号“”
+ afraid="there is only 'fear' word itself",
+ sad="cheer up",
+ angry="calm down now"
+ )
> res
[1] "cheer up"
二、循环语句
循环语句的功能是重复执行一个语句集合,重复执行的原因是,(1)输入数据有多个独立的元素,每次循环执行一次循环(2)循环语句是迭代计算方式。
1.for循环语句
语法形式:
for(循环变量i in 范围d)
{
... ...
}
范围d是向量x={80,60,60,88,92} 或者1:100等。for语句{}中的内容称为语句体。注意:语句体中的语句后面不能有逗号。
eg5.1 不妨设剑桥大学计算机系学生金城武和梁朝伟大学一年级下学期成绩见表。梁朝伟是班级第一名,金承武需比较自己的成绩,以提高大学二年级的学习水平。统计所有课程的总分、平均分,分析差距最大的课程应重点提高,专业课和基础课的平均分比较确定努力的方向,并且打印报表。
表大学一年级下学期成绩
姓名 |
高等数学 |
英语 |
高等物理学 |
pascal语言 |
计算方法 |
金承武 |
70 |
61 |
50 |
75 |
60 |
梁朝伟 |
91 |
90 |
88 |
98 |
87 |
R语言源程序
>da1=c(70,61,50,75,60)
>da2=c(91,90,88,98,87)
>df1=rbind(da1,da2)
>sum=c(0,0,0,0,0,0) #不能用sum[1:6]=0.sum是总分
>means=sum #means是平均分。若后面将引用向量的元素,则先声明向量
>dife=c(0,0,0,0,0) #课程成绩差距向量
>dim(df1)
[1] 2,5
>class(df1)
“matrix” #df1是矩阵应转换为数据框
>df1=as.data.frame(df1)
>for(i in 1:2)
+{
sum[i]=0,
for(j in 1:5)
{
sum[i]=df1[i,j]+sum[i], #总分sum[]
if (j==3)
sum[i+2]=sum[i] #基础课总分
if (j==5)
sum[i+4]=sum[i]-sum[i+2] #专业课总分
if(i==2)
dife[j]=df1[i,j]-df1[i-1,j] #差距 deat[]
}
means[i]=sum[i]/5 #平均分 means[]
means[i+2]=sum[i+2]/3 #基础课平均分
means[i+4]=sum[i+4]/2 #专业课平均分
+}
>princp=c(1)
>for(i in 1:5) #简单选择排序,找到最大的课程差距
+{
if dife[i]>princp{
princp=dife[i]
prini=i
}
+}
>
>df2=df1[,1:2]
>for(i=1:2)
{
df2[i,]=c(sum[i],means[i])
}
>
> sum
[1] 316 454 181 269 135 185
> means
[1] 63.20000 90.80000 60.33333 89.66667 67.50000 92.50000
> dife
[1] 21 29 38 23 27
>princp
[1] 38
>df1[1,prini]
高级语言传统方式应用循环语句,是元素级df1[i,j]的访问方式,因此必须首先声明。而R语言对向量复制,并不是单个元素的访问方式,称为向量编程方式,而且还
循环变量i并不一定是整型,可以是字符串,这与C语言的印象不同。
eg6 循环变量i是字符串
>mood=c("pleased","afraid","sad","angry")
>j=1
>for(i in mood)
{
cat("循环次数",j," ")
j=j+1
cat("i=",i," ")
}
##循环次数 1 i= pleased
##循环次数 2 i= afraid
##循环次数 3 i= sad
##循环次数 4 i= angry
2.break语句
break语句跳出循环。
eg5.2 例如,这所大学规定学生有一门课程不及格,则不能得到奖学金。设计算机系学生总数2017位,原始数据框df2的格式与表格1相同,则通过初步奖学金认定的人数为
for(i in 1:2017)
for(j in 2:6)
if (df2[i,j]<60)
{cat(‘学生姓名’,df2[i,1],’不能参加奖学金评选’)
break
}
当发现一个学生有不及格的课程时,就不需要判断所有课程的等级,因此用break语句可提高程序效率。
3.while语句
while语句在输入数据符合条件表达式时,执行语句体,否则跳出循环继续执行程序的下一条语句。
语法形式:
while(条件表达式)
{
... ...
}
当while语句的条件表达式=TRUE时,只有用break语句跳出循环。
eg6.当夏天的时候,树木应多浇水以防止干旱枯黄,一个星期的每天都浇水,但是中午不能浇水,而冬天的时候则要少浇水,以免导致树木根部被淹而发生腐根现象,一星期只能浇一次,并且常常在一天气温高时浇水。打印一星期内的日常浇水时间表。
seanor=c("summar","winter")
watertime1=c(8:00,10:00,17:00,21:00)
watertime2=c(11:00,14:00)
times=rep(0,7)
daysean="summar"
date=1
i=1
while(date<=7)
{
times[date]=ifelse(daysean==seanor[1],watertime1[i],watertime2[i])
date=date+1
i=i+1
if(date==7) date=1
if(daysean==seanor[1])&(i==5)||(daysean==seanor[2])&(i==3)) i=1
}
cat("一周浇水时间",times[date])
##一周浇水时间 8:00 10:00 17:00 21:00 8:00 10:00 17:00
3.repeat语句
repeat语句没有逻辑判断跳出条件,因此必须应用break语句。
语法形式:
repeat{
... ...
if(cond) break
}
4.next语句
next语句的功能与C语言的continue一样。跳过本次循环其他部分,到下一次循环开始执行。
eg7.饮酒与工资的关系
一个企业生产部门有职工19人,员工工资salary=c(4000,3900,5000,2900,4200,4100,3800,5100,3900,3600,4500,3800,2600,4300,4500,3700,4300,3800,20000),对他们饮酒状况进行调查研究,按不饮酒1、白酒2、葡萄酒3、啤酒4分成四类。数据是:1 2 1 2 3 1 3 1 4 3 1 2 2 1 1 1 4 2 3。部门经理的工资是20000 元一个月,远远大于普通员工的工资。发现职工饮酒与工资等级的关系,以提高员工素质,建设现代企业。
wine=c(1,2,1,2,3,1,3,1,4,3,1,2,2,1,1,1,4,2,3)#饮酒调查数据
salary=c(4000,3900,5000,2900,4200,4100,3800,5100,3900,3600,4500,3800,2600,4300,4500,3700,4300,3800,20000)
#生产部门职工工资
alcdrink=c("不饮酒","白酒","葡萄酒","啤酒")
levsal=c(0,0,0,0,0)
drink2=drink3=drink4=drink5=c(0,0,0,0)
for(i in 1:19)
{
if(salary[i]==20000)
{
cat("部门经理工资","20000",alcdrink[wine[i]]," ")
next
}
if(salary[i]>=5000)
{
levsal[5]=levsal[5]+1
drink5[wine[i]]=drink5[wine[i]]+1
next
}
if((salary[i]>=4000)&(salary[i]<5000))
{
levsal[4]=levsal[4]+1
drink4[wine[i]]=drink4[wine[i]]+1
next
}
if((salary[i]>=3000)&(salary[i]<4000))
{
levsal[3]=levsal[3]+1
drink3[wine[i]]=drink3[wine[i]]+1
next
}
if((salary[i]>=2000)&(salary[i]<3000))
{
levsal[2]=levsal[2]+1
drink2[wine[i]]=drink2[wine[i]]+1
}
}
cat("工资5000以上的职工","不饮酒",drink5[1],"白酒",drink5[2],"葡萄酒",drink5[3],"啤酒",drink5[4],"\n ")
cat("工资4000以上的职工","不饮酒",drink4[1],"白酒",drink4[2],"葡萄酒",drink4[3],"啤酒",drink4[4],"\n ")
cat("工资3000以上的职工","不饮酒",drink3[1],"白酒",drink3[2],"葡萄酒",drink3[3],"啤酒",drink3[4]," \n")
cat("工资2000以上的职工","不饮酒",drink2[1],"白酒",drink2[2],"葡萄酒",drink2[3],"啤酒",drink2[4],"\n ")
##部门经理工资 20000 葡萄酒
##工资5000以上的职工 不饮酒 2 白酒 0 葡萄酒 0 啤酒 0
##工资4000以上的职工 不饮酒 5 白酒 0 葡萄酒 1 啤酒 1
##工资3000以上的职工 不饮酒 1 白酒 3 葡萄酒 2 啤酒 1
##工资2000以上的职工 不饮酒 0 白酒 2 葡萄酒 0 啤酒 0
以上传统编程方法,可用R语言的向量式编程和数据框生成factor因子变量,参考第四节因子和列表。
正在写作:《R语言编程与应用》(纯属非正式名称)第二章第六节