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語言編程與應用》(純屬非正式名稱)第二章第六節