1. 程式人生 > >R語言學習筆記之三

R語言學習筆記之三

結構 urn padding 效果 rand html 創建 字符 pri

僅用於記錄R語言學習過程:

內容提要:條件與循環

正文:

格式:

條件

ü if (條件) 執行的程序 else

ü if (條件)

{函數體 (分行,或者用;隔開)

} else

返回值

ü 不支持向量話操作(例4)

循環:

ü repeat { if(條件)語句體 設置break條件 else

執行程序

}

ü while (條件){語句體

}

ü 常用:for(條件){語句體

}

ie: for (I in 1:10) {

print(i)

}

ü

set.seed(2017)

x <- sample(10:100,10)

y<- sample(1:100,10)

z <- NULL

for ( i in 1:10) {

if (x [i] > y[i]) {

z = append(z,x[i])

}

}

以下內容來自轉載:

http://www.dataguru.cn/thread-562515-1-1.html

R語言的控制結構可以對R程序進行流程控制,這些控制結構與你在其它編程語言中看到的非常相似。基本的結構如下所示。

  • if/else : 用於邏輯條件
  • for : 用於執行國定次數循環
  • while : 當某個條件成立時while結構執行循環
  • repeat : 可以簡單的直接地執行無限循環
  • break : 可讓程序從任意循環中跳出
  • next : 忽略循環中的某次叠代
  • return : 可以用來退出函數

因此,大多數控制結構不是那些你在交互式會話中使用的,也不像在R語言的命令行裏執行命令,這些控制結構通常是你寫R程序或R函數時會用到的。

條件控制 if

第一個結構是 if 結構。這是一個帶有 else 的 if 結構,它可以用來測試邏輯條件,並基於條件的真偽來執行命令。如果條件成立,程序會做某件事,否則就做另一件。這是一種典型的結構,而 else 部分不是必須的。因此當你需要條件成立時執行某命令,只需要 if 語句即可。但如果你需要執行某個備選命令,那麽就需要 else 部分。如果你需要檢查多個條件,那你可以在 if 後面增加 else if 和 else 的結構。像這樣的結構裏,可以有任意數量的 else if,但必須以的 else 語句結尾。

if(<condition>) { ## do something} else { ## do something else}if(<condition1>) { ## do something} else if(<condition2>) { ## do something different} else { ## do something different}

在R語言裏有多種方式可以構建 if/else 的結構,如果你沒見過類似這樣的結構的話,那它確實與其它語言略有不同。下面第一個是比較標準的結構。

if(x > 3) { y <- 10 ##如果 x 大於3,y 就等於10} else { y <- 0 ##否則如果 x 不大於3,y就等於0 } ##根據 x 與 3 比較的不同結果,賦給 y 不同的值

但在R語言中,你可以使用另外一種方法,可以讓 y 等於整個 if/else 結構。這也是個有效的表述。有時候你在讀代碼時,因為它會讓你明白整個 if/else 結構就為了對 y 進行賦值,所以這種類型的寫法是很有用的。

if(x > 3) { 10} else { 0}

當然,else 部分也不是必須的。可以只是測試條件成立,然後執行緊接著的大括號裏面的命令,或者剛巧條件不成立,那就什麽也不做。如果有需要,你可以在一行裏測試多個條件。

if(<condition1>) {}if(<condition2>) {}循環結構一 for

下面這個結構是 for 結構,這可能會是你在R語言中用到的最常見的循環運算符。基本思路是:設一個循環下標,通常命名為 i, 當然如果有多個循環也可以用 j、 k、 l 等等,循環下標通常會遍歷一個整數的數列。當循環結束時,它就繼續執行下一段代碼主體。

舉例來說,這裏有一個 for 循環,它從數字1遍歷到10(中間用冒號隔開),然後創建了這個1到10的數列。

for(i in 1:10) { print(i) ##在每次叠代時輸出 i}

在R語言裏可以用不同方式來使用 for 結構,而且R語言在索引R對象時很靈活。

##用字母a、b、c、d構建一個字符向量,下面這幾個 for 循環例子是等價的x <- c("a", "b", "c", "d") ##第一個例子:用從1到4的整數數列作為下標 i 的取值,每次打印出 x 的第 i 個元素,因此這個循環就打印出"a", "b", "c", "d"for(i in 1:4) { print(x)} ##第二個例子:使用 seq_along 函數,它的輸入是一個向量,之後它會創建一個與該向量等長的整數數列。 x 向量,長度為4,所以它會創建一個從1到4的整數數列,這和用1:4的語句獲取數列的結果是完全一樣的。但這是基於變量 x 的長度生成生成的數列,然後下標變量 i 遍歷這個數組,打印出"a", "b", "c", "d"for(i in seq_along(x)) { print(x)} ##第三個例子:取下標變量 letter,它會從向量本身取值(沒有理由說下標變量一定要是整數),可以從任意向量中提取元素,所以這個 for 循環遍歷 x 向量中的字母a, b, c, d,然後就打印出字母本身for(letter in x) { print(letter)} ##最後這個例子除了沒帶{}跟第一個一樣,如果一個 for 循環裏只包含單個表達式,那你將之放一行,並省略{},這樣做有時候更好用,因為更緊湊一些for(i in 1:4) print(x)

for 循環可以嵌套,所以可以把一個 for 循環放到另一個 for 循環裏面。

通常的例子是,有一個二維矩陣,需要對它做一個行循環再做一個列循環。這裏外層循環的下標為 i 作為行循環,再用 seq_len()函數(這個函數的輸入是一個整數,這個例子裏剛好是 x 的行號)創建一個整數數列。

這個特定的矩陣有兩行,因此會產生一個1和2組成的數列。類似地,嵌套循環裏的 j 下標用列號產生數列,這個矩陣有三列,因此這個seq_len()會產生1到3的整數數列。然後這個雙層嵌套的循環就打印出這個矩陣裏所有的元素。但一點需要註意:雖然理論上沒問題但循環嵌套較好不要超過兩到三層,因為超過的話代碼讀起來會有些困難。如果代碼有兩到三層的嵌套,會很難懂。雖然有時候這麽做很合邏輯,但很多時候總有替代的辦法,比如說用函數,等。

x <- matrix(1:6, 2, 3)for(i in seq_len(nrow(x))) { for(j in seq_len(ncol(x))) { print(x[i, j]) }}while

while循環是R中另一種主要的循環結構,其基本原理是,它有一個邏輯表達式,循環按照此邏輯表達式的值來運行。

這裏有一個很簡單的循環:

count <- 0 ##將計量變量初始值設定為0while(count < 10) { print(count) count <- count + 1} ##當計量變量小於10時,該循環輸出該計數變量,然後將這個計數變量的值加1,一旦計數變量的值達到10,循環就會停止

從該循環可以看出, while 循環很有用,因為它通常比較方便閱讀。可以清楚地看到,當計數變量的值大於或等於10時,這一循環就會停止運行,接著會運行下一段代碼主體。這些都表明 while 循環是比較易讀的。當然,使用 while 循環時必須小心一點,因為從技術層面來說 while 循環是無限循環,所以要確保終止的條件一定會達成,否則程序永遠不會結束。在上面這個例子中,很顯然循環最後會終止。但是如果代碼再復雜一點就不容易確認 while 循環是否會停止了。如果想要保險一點,就使用 for 循環,它對循環執行次數具有硬性限制的循環。但並不是說你不要使用 while 循環,只不過在你使用它們時務必要謹慎。

在 while 循環中我們可以使用邏輯運算符來驗證多重條件或者各種類型的結構,例如 if 語句。

z <- 5 ##把變量 z 的初始值設為5while(z >= 3 && z <= 10) { print(z) ##當 z 的取值介於3和10之間時,程序會輸出 z 的值 coin <- rbinom(1, 1, 0.5) #rbinom()模擬拋擲均勻硬幣 if(coin == 1) { ## random walk z <- z + 1 ##如果硬幣拋出一個1就給 z 加1 } else { z <- z - 1 ##如果拋出0或其它值,將把 z 減1 }}

這是一個小型的隨機遊戲,z 的值會根據拋硬幣的結果而變大或變小。這裏可以看到,這段 while 循環包含了隨機數的生成,所以我們很難判斷它何時會結束,z 值會上下波動直至它最終達到10或者小於等於3。這段代碼看起來挺好的,但要小心,它的運行時間可能會很長。還有一個技術層面的事情需要註意,當R檢驗具有多個表達式的條件時,條件總是自左向右被檢驗,所以程序會檢查最左邊的條件是否為真,然後在檢查下一個條件,都為真時程序會繼續進行,進入循環的主體。

循環結構 repeat

repeat 結構發起的基本都是無限循環,我們一般不會把這個結構歸為R中常用的控制結構,但我們仍然會在某些場合用到它。退出 repeat 循環的方法是調用 break 函數。顯而易見,除非你想永遠運行程序,否則你將不得不在某個節點調用 break 函數。這裏有一個簡單的例子:

x0 <- 1 ##把 x0 的初始值定為1tol <- 1e-8 ##設定一個容差,其值為10的負8次方repeat { x1 <- computeEstimate() ##估算 x 的值 if(abs(x1 - x0) < tol) { break ##如果 x1 與 x0 的差的值小於容差,循環停止 }else { x0 <- x1 }}

在許多類型的優化算法中,這是一種常見的公式化做法。舉例來說,如果你想解一組方程或者求函數的較大值,通常會一次又一次的進行叠代,當你的估計值彼此越來越接近,循環就會終止,這表明你已經接近目標函數的較大值或者最小值。理論上來說,這是一個完美而合理的構造,但如果想要持續地循環利用這一算法知道兩個值足夠接近。

問題就來了,首先,我們需要保證該算法能夠收斂,但並非所有的算法都具有這種收斂的特性。其次,算法的效果還部分取決於容差,一般來說,容差越小,循環運行的時間越長。通常來說,難以預測循環的時間,這種算法可能會有點危險,理論上來說它甚至可以永遠運行,而你沒有辦法保證程序會在某個節點終止。盡管從理論上來說這一結構是正確的,通常我們不認為它是一個好方法,所以較好是使用 for 循環。

next,return

最後2個控制結構要素是 next 函數以及 return 函數。 next 函數可以在任何類型的循環結構裏使用,主要用來跳過某次叠代。這裏有一個基本的 for 循環,該循環會運行100次叠代,但想要跳過開始的20次叠代只執行第21次到第100次叠代,所以寫了一個簡單的 if 條件(如果 i 小於等於20就跳過叠代)調用了 next 函數,然後進入下一次叠代。故 next 函數是一種跳過叠代的方法,而 break 函數是一種完全跳出循環的方法。

for(i in 1:100) {if(i <= 20) { ## 如果 i 小於等於20就調用 next 函數跳過叠代 next} ## 如果 i 大於20就執行 for 循環中 next 語句後面的代碼}

return 函數是另一種用來跳出循環的函數,主要用來跳出一個函數(會使之跳出整個函數),然後返回你傳遞給它的值。但要註意 return 函數也可以終端程序的運行。

R語言學習筆記之三