R語言 控制流:for、while、ifelse和自定義函數function

2021-02-14 數據分析1480

行列引用、條件篩選等可以簡單的數據管理,但其在無法有效處理多次、多重、有規律的循環和判斷問題,而控制流卻可以通過循環、判斷、跳錯等等操作輕鬆處理此類問題。

  

以下概念貫穿控制流張杰的內容,需要首先認識:

語句(statement):單獨或組合語句,一般在{}中以;分隔 。例如:{語句1;語句2} 

條件(cond): 最常見的是判斷一個條件是否成立。如果成立則執行一條語句或者一個代碼塊,比如上例a是否小於b,如果小於則輸出b  

表達式(expr):一個數值或字符的求值語句,多用於數據計算過程或賦值

序列(seq):一個數值或者字符序列 

                                                                                                              

目錄

1 分支控制     

1.1 if-else

1.2 ifelse

1.3 switch

2 循環控制流

2.1 for循環

2.2 while循環

2.3   repeat 循環      

3 function函數(一次編寫,多次調用,一勞永逸)

3.1 自定義函數編寫

3.2 source()文件間調用自定義函數

分支和循環是通用程式語言中常見的兩大控制流。其中,分支控制是根據條件表達式的結果,執行不同的代碼段;循環控制是根據條件重複執行代碼塊,為了避免無限循環,可以根據條件結束循環。接下來分別從分支控制和循環控制,對R語言中的控制流做簡單講述。

正文

1 分支控制     

 

1.1 if-else

經典的流程控制關鍵字是if-else,並可以把多個if-else語句連接到一起

#if-else分支控制流語法if ( test_expression1) {statement1} else if ( test_expression2) {statement2} else {statement3}

示例

#嵌套用法> a=5> b=6> if (a < b) {a <- -1+ } else if (a == b) {a <- 0+ } else {a <- 1}> print(a)[1] -1

1.2 ifelse

ifelse控制可以理解為一個函數。

#ifelse語法ifelse(條件表達式, true, false)

示例

> x <- factor(sample(letters[1:5], 10, replace = TRUE))> x [1] a a c d a b d b d dLevels: a b c d> ifelse(x %in% c("a", "b", "c"), x, factor(NA)) [1]  1  1  3 NA  1  2 NA  2 NA NA

注意:返回值的class屬性跟test表達式相同,其mode屬性是由 yes 或 no表達式確定的。當ifelse()用於返回Date類型的對象時,返回值是numeric類型,而不是Date類型,這是因為返回值的class是由test表達式決定的。

> dates <- as.Date(c('2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04', '2011-01-05'))> dates[1] "2011-01-01" "2011-01-02" "2011-01-03" "2011-01-04" "2011-01-05"> dates <- ifelse(dates == '2011-01-01', dates - 1, dates)> dates[1] 14974 14976 14977 14978 14979
#解決方案是:把返回值的class重新設置為Date類型。> dates <- as.Date(c('2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04', '2011-01-05'))> dates[1] "2011-01-01" "2011-01-02" "2011-01-03" "2011-01-04" "2011-01-05"> dates <- ifelse(dates == '2011-01-01', dates - 1, dates)> dates[1] 14974 14976 14977 14978 14979> class(dates) <- 'Date'> dates[1] "2010-12-31" "2011-01-02" "2011-01-03" "2011-01-04" "2011-01-05"

1.3 switch

如果分支較多,可以使用switch函數實現分支的選擇,switch函數的第一個參數是表達式(exp),通常是一個字符串。當表達式(exp)匹配後續的參數名(即變量名)時,返回參數的值

#switch語法switch(字符,參數名1='參數值2',參數名2='參數值2',……"其他")

示例

#當表達式(exp)匹配後續的參數名(即變量名)時,返回參數的值> t = "r"> switch(t,r='re',g='gr',b='bl',"error")[1] "re"
#如果不匹配任何參數名,switch函數不返回任何值,可以添加一個匿名的參數,#當表達式(exp)匹配不上任意一個命名參數時,switch函數將返回匿名參數的值:> t = "xs"> switch(t,r='re',g='gr',b='bl',"error")[1] "error"

2 循環控制

repeat、while和for是常見的循環控制語句。

2.1 for循環

使用迭代器和一個向量參數,在每個循環中,迭代器變量從向量中取得一個值,直到迭代所有得向量

#語句for (變量 in 序列/字符集) {語句/表達式}

示例

#依次執行序列/字符集中的每一個數據+print語句> for (i in 1:5) print(letters[i])[1] "a"[1] "b"[1] "c"[1] "d"[1] "e"
#依次執行序列/字符集中的每一個數據+表達式+print語句> for (i in 1:5) {j = j + i; print(c(i,j))}[1] 1 1[1] 2 3[1] 3 6[1] 4 10[1] 5 15> j = 0> for (i in 1:5) {j = j + i; print(c(i,j))}[1] 1 1[1] 2 3[1] 3 6[1] 4 10[1] 5 15> print(j)[1] 15

2.2 while循環

先檢測條件,如果條件為TRUE,執行code;如果條件為FALSE,結束循環

示例

> i=5> while (i >0) {j = i; i=i-1 ; print(c(j,i))}[1] 5 4[1] 4 3[1] 3 2[1] 2 1[1] 1 0

  

2.3   repeat 循環                                                                                   repeat 循環:先執行代碼,遇到break關鍵字,結束循環

repeat {code if(條件) break}

示例

> i=100> sum=0> repeat + {+   if(i==0)+     break+   sum=i+sum+   i=i-1+ }> print(sum)[1] 5050


3 function函數(一次編寫,多次調用,一勞永逸)

3.1 自定義函數編寫

R通過function關鍵字定義函數,函數主要由函數名稱,參數,運行的代碼塊和返回值組成,函數名稱是變量,參數是調用函數時需要傳遞的形式參數;代碼塊是由由大括號構成,是調用函數時需要執行的代碼邏輯;R的函數不需要顯式地使用return關鍵字明確返回值,R函數的計算的最後一個值將自動作為返回值。    

#語法myfunc=function(arg1,arg2,....) #參數{表達式/循環/print語句等return(object)  #返回輸出的對象}

 

示例1:簡單計算

> avg <- function(a,b)+ {+ return(mean(c(a,b)))+ }> avg(4,5)[1] 4.5
> avg <- function(a,b)+ {+ mean(c(a,b))+ }> avg(4,5)[1] 4.5

                                                                                                               示例2:矩陣計算     

> mat1<-matrix(c(1:12),nrow = 3,ncol = 4);mat1     [,1] [,2] [,3] [,4][1,]    1    4    7   10[2,]    2    5    8   11[3,]    3    6    9   12> mat2<-matrix(c(1:24),nrow = 4,ncol = 6);mat2     [,1] [,2] [,3] [,4] [,5] [,6][1,]    1    5    9   13   17   21[2,]    2    6   10   14   18   22[3,]    3    7   11   15   19   23[4,]    4    8   12   16   20   24> f<-function(x,y)+ {+   xcol<-dim(x)[2]+   yrow<-dim(y)[1] +   m<-dim(x)[1]+   n<-dim(y)[2]+   if(xcol!=yrow)   #向量乘積的要求+   {+     print("error")+     return(0)+   }+   else #if-else語句+   {+     mat<-matrix(0,nrow=dim(x)[1],ncol=dim(y)[2])  #首先要定義一個矩陣作為結果矩陣+     for(i in c(1:m))+       for(j in c(1:n))+         mat[i,j]<-sum(x[i,]*y[,j])  +     return(mat)+   }+ }> f(mat1,mat2) #調用自定義矩陣計算函數     [,1] [,2] [,3] [,4] [,5] [,6][1,]   70  158  246  334  422  510[2,]   80  184  288  392  496  600[3,]   90  210  330  450  570  690> mat1%*%mat2  #驗證     [,1] [,2] [,3] [,4] [,5] [,6][1,]   70  158  246  334  422  510[2,]   80  184  288  392  496  600[3,]   90  210  330  450  570  690   

3.2 source()文件間調用自定義函數

在R語言裡我們需要藉助source()函數。

示例:自定義avgfunction函數並保存到avgfunction.R文檔裡

#avgfunction代碼avgfunction = function(x){sum(x)/length(x)}

source('avgfunction.R') #注意需用引號將文檔名引起來,當avgfunction.R與operate.R在同一路徑時,不需要加路徑 

將被調用的函數放置在電腦桌面(C:/Users/ysl/Desktop/),工作目錄(C:/Users/ysl/Documents)

> source('avgfunction.R') #因被調用函數與當前工作空間不一致,提示錯誤#Error in file(filename, "r", encoding = encoding) : 無法打開鏈結#此外: Warning message:#In file(filename, "r", encoding = encoding) :# 無法打開文件'avgfunction.R': No such file or directory
#重新調整在source()添加完整的文件路徑,即可成功調用> source('C:/Users/ysl/Desktop/avgfunction.R')> avgfunction(c(1:20))[1] 10.5

                                                                                                               

【推薦書籍】

相關焦點

  • R語言之控制流的使用方法
    if或switch分支語句2)for循環3)while循環下面就說說這幾種控制流,並講解我工作中的用法。一、if或switch分支語句首先看一下if分支語句,一般有雙分支和多分支。關於這兩種分支我們看下圖:對於二分支,我個人更喜歡使用ifelse()函數,該函數是R語言內置的函數,運行速度是非常快的。
  • R語言中通過自定義函數大顯神通
    R語言提供了大量的包為用戶解決各方面的問題,同時,R語言中允許用戶編寫自己的函數來解決實際問題。自定義函數概述在R語言中,用戶自定義的函數語法格式:functionname <- function( arglist ) exprreturn (value)上面的語法中
  • 【R函數學習】R語言時間序列函數整理
    #arma模型library(fUnitRoots) #進行單位根檢驗library(FinTS) #調用其中的自回歸檢驗函數library(fGarch) #GARCH模型library(nlme) #調用其中的gls函數library(fArma) #進行擬合和檢驗【基本函數
  • R語言:Newton法、似然函數
    hello,大家好,上一篇分享了如何用R語言實現蒙特卡洛模擬,並用蒙特卡洛模擬計算了分布的均值和方差,今天給大家分享如何用R語言來進行矩估計和似然函數的求解。因為在求解矩估計和似然函數時,可能會遇到非線性方程組,所以先給大家介紹一下如何用Newton法來求解非線性方程組。
  • 乾貨 掌握R語言中的apply函數族
    原因在於R的循環操作for和while,都是基於R語言本身來實現的,而向量操作是基於底層的C語言函數實現的,從性能上來看,就會有比較明顯的差距了。那麼如何使用C的函數來實現向量計算呢,就是要用到apply的家族函數,包括apply, sapply, tapply, mapply, lapply, rapply, vapply, eapply等。
  • Learn R:如何自定義IRR函數
    關於使用Excel內置公式計算IRR的相關文章已有很多,那麼為何要使用R語言編寫IRR函數呢?原因就在於R語言可以藉助向量化操作方式實現IRR的批量查詢。1、自定義函數在編寫IRR之前,我們先簡單回憶一下初等數學中一個最簡單的函數形式:f(x,y)=x+yR語言自定義函數非常簡單,其形式如下:f <- function(x,y){x + y}編寫函數的語法包括:
  • while、for、try except語句中的else
    下面要看的是for,while循環和try異常處理語句中的else的用法。一、for,while循環中的elsefor,while循環中,else用於循環正常結束,且循環體中沒有break、return和異常拋出,則執行else語句塊中的內容。例如,我們判斷列表ls中是否全是奇數。普通情況下,需要引入一個標誌變量allOdd,指示所有變量都是奇數,有偶數出現則將此變量設為False。
  • ...函數式宏定義不能用普通函數代替嗎?為什麼要使用do{}while(0...
    C語言中的「函數式宏定義」C語言中的 define 宏定義可以像函數那樣接收參數(這種宏定義常被稱作「函數式宏定義」),不過不能像函數那樣提供參數的類型檢查,這個特點在有些程式設計師看來是不安全的。C語言中 define 宏定義的「陷阱」C語言中的「函數式宏定義」雖然使用起來很像函數,但它實際上並不是函數,讀者千萬不能忽視這一點,不然可能會寫出具有隱患,甚至嚴重錯誤的C語言程序。
  • R語言從入門到精通:Day6-R語言數據操作進階及控制結構
    R中,概率函數形如 :[dpqr]distribution_abbreviation()其中第一個字母表示其所指分布的某一方面:d = 密度函數(density)p = 分布函數(distribution function)q = 分位數函數(quantile function)r = 生成隨機數(隨機偏差
  • R語言時間序列函數大全(收藏!)
    library(fGarch) #GARCH模型library(nlme) #調用其中的gls函數library(fArma) #進行擬合和檢驗數學函數abs,sqrt:絕對值,平方根 log, log10, log2 , exp:對數與指數函數 sin,cos,tan,asin,acos,atan
  • C語言for,while,if-else,return語句的綜合使用
    #includevoid main(){int i,j,k;j=10;while(j--) //j控制換行{ i=10-j;while(i--) //i控制循環,而且控制的是緊隨其後的語句,即printf("*");而控住不了printf("");if(i<3) //if-else的用法是滿足if則執行其後的語句,否則執行else。
  • K&R之經典C語言第三課:8種控制流
    The braces that surround the statements of a function are one obvious example; braces around multiple statements after an if, else, while, or for are another.
  • 現代C++函數式編程之function compose
    Composing function calls假設我們有兩個函數f和g,組合f,g意味著f(g(x)), 即先計算函數
  • STM32+Keil 如何使用printf函數?
    那麼只能通過程序向硬體串口發數據了,這樣調用的時候用自定義的函數即可,也很方便,例如:本文引用地址:http://www.eepw.com.cn/article/201611/317105.htmvoid send_char_to_usart(unsigned char c){}但是可否直接使用printf函數呢?
  • 自定義 LLVM PASS 實現 函數耗時插樁統計
    GENERATE_XCODE_FLAG=0CLEAR_BUILD_FLAG=0while getopts 'hbxc' OPT; do case $OPT in b) BUILD_FLAG=1;; x) GENERATE_XCODE_FLAG=1;; c) CLEAR_BUILD_FLAG=1;;
  • R語言系列3:高級數據管理
    R語言系列3:高級數據管理此文內容為《R語言實戰》的筆記,人民郵電出版社出版。在第5章,我們主要瀏覽R中的多種數學、統計和字符處理函數,了解如何自己編寫函數來實現數據處理和分析任務,並了解數據的整合和概述方法以及數據集的重塑和重構。5.2 數值和字符處理函數R中作為數據處理基石的函數,可以分為數值函數(數學、統計、概率)和字符串處理函數。
  • 零基礎學Python--分支與循環以及函數
    一個通用的分支程序流程如下圖:在Python語言裡面,將所有非零和非空的值都定義為True。並且在Python裡面支持如下類型的代碼結構:if ......函數函數其實很簡單,我們在上述代碼中看到的print就是一個函數了!那麼我們如何來定義一個函數呢?
  • Pascal中自定義函數
    Pascal中自定義函數 http://gaokao.eol.cn/  來源:  作者:信息女士  2010-09-21  字體:大 中 小  PROGRAM e5(inmput,output);
  • R語言——使用apply function替代for loop循環語句
    不過在進行結果重現的過程中,我用R始終沒辦法得到和作者一致的結果,而作者又是用的Stata,所以我目前還在找是哪裡出現了問題。如果之後問題解決了,我會再把這篇論文推出來的。有興趣的朋友,可以點擊文末閱讀原文查看這篇論文。既然難的做不了,今天就先講個簡單的,R語言裡面for loop的替代者apply function。
  • R用戶Python指南:文件和異常
    本文為R用戶Python指南系列第9篇,Python代碼主要取自《Python編程:從入門到實踐》第10章,R代碼根據Python代碼複寫。本文使用rmarkdown生成格式,代碼塊中#之後的內容為注釋,##之後的內容為代碼輸出結果。本文使用的R包主要為stringr、readr和jsonlite,需預先加載。