iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 8
1
Big Data

R語言與機器學習見面會系列 第 8

Day08 R語言的函式(Function)

Write once, run anywhere "at R"

我們借Java語言跨平台的slogan來形容今天的主角: Function

函式是一組陳述式的區塊,可以將重複會執行多次的陳述式獨立抽出來,方便隨招隨停。程式是否結構化、模組化,函式是關鍵之一,今天我們花一些時間來複習幾個內建函式,然後試試看自己寫幾個函式,有預設值輸入、傳址呼叫的。

進入R語言基礎的Part3: Function。

R語言函式:


函式(function)可以輸入參數、執行陳述式,最後回傳輸出(return),R語法函式的參數會放在括號中,如下以逗號分隔。

function(參數1,參數2)
{
    return(回傳參數)
}

*空括號表示函式不需要任何參數。

R語言內建的函式非常完整,從一般的數學算數、三角函數、排序、字串、日期及統計函式都有支援,再加上安裝Package後新增的函式,如果我們能熟悉且善用,在R語言中真正寫起程式的機會很少,我們就能將時間專注在使用上。

接下來,我們在資料夾MyR新增一支Day08.R
http://ithelp.ithome.com.tw/upload/images/20161209/20103434vR3oxlq2ZH.png

內建算數函式


假設我們有以下需求:
列印1:10的數字
計算1+2...+100的平均值
計算1+2..+100的總和

分別可以用以下內建函式來解題:

  • seq : Sequence Generation 連續數產生(也可以設定起始結束及間隔值參數)
  • mean: Arithmetic Mean 算數平均
  • sum: Sum of Vector Elements 向量加總

在Day08.R中輸入程式碼

#Create a sequence of numbers from 1 to 10. 
print(seq(1, 10)) 
 
#Find mean of numbers from 1 to 100. 
print(mean(1:100)) 

#Find sum of numbers frm 1 to 100. 
print(sum(1:100)) 

執行結果
http://ithelp.ithome.com.tw/upload/images/20161209/20103434b2Nv4vylKV.png

不用寫for迴圈,就完成了向量運算。

自建函式


假設我們想計算一個數值陣列(1到5)中有多少個奇數。

在Day08.R中輸入程式碼
程式規格:
奇數就是被2除會餘1的數字, 利用for迴圈依序查輸入的一組數值class,若除2餘1,就將odd counter+1

#Create a function to get Odd count 
OddCount.function <- function(x) { 
    o <- 0 
    for (n in x) { 
        if (n %% 2 == 1) { 
            o <- o + 1 
        } 
    } 
    return(o) 
} 
  
#Call the function  
OddCount.function(c(1,2,3,4,5)) 

http://ithelp.ithome.com.tw/upload/images/20161209/20103434Hqg5zFztxS.png

奇數有3個,回傳值只要在函式中寫return(o)

帶有預設值的自建函式


假設我們新增一個乘法運算的方法,同時賦予預設值,新的乘法方法功能:

  • 如果有輸入參數,依照輸入的參數組相乘,並回傳乘積
  • 如果沒有輸入參數,依照預設參數組7、9,回傳乘積63

在Day08.R中輸入程式碼

#自建函式(有預設值) 
#Create a function with arguments. 
multiply.function <- function(x = 7, y = 9) { 
    result <- x * y 
    print(result) 
} 
 
#Call the function without giving any argument. 
multiply.function() 
 
#Call the function with giving new values of the argument. 
multiply.function(6, 8)

http://ithelp.ithome.com.tw/upload/images/20161209/20103434jLBIcwLK4C.png

第一次執行沒有輸入參數,使用預設值7 x 9 = 63,第二次使用輸入參數 6 x 8 = 48

41J、記者正確!

Call by value and Call by reference


R語言的函式通常是傳值呼叫

call by value

add.fucntion <- function(x) { 
    x <- x + 1 
    x 
} 
x <- 1 
add.fucntion(x) 
x 

http://ithelp.ithome.com.tw/upload/images/20161209/20103434whKSo9s0pD.png

函式中 x = 2,但呼叫完函式後,外層的x還是1,原來外層x位址的值並不會改變。

但如果想要傳址呼叫? 除了 x <- f(x)重新指派外,因為只能回傳一個值,來找第二種解法,可以在函式內改變x的值。

call by reference

add.fucntion <- function(x) { 
    value <- x + 1 
    eval.parent(substitute(x <- value)) 
} 
x <- 1 
add.fucntion(x) 
x 
#help(eval.parent) Evaluate an (Unevaluated) Expression 
#help(substitute) Substituting and Quoting Expressions 

執行結果
http://ithelp.ithome.com.tw/upload/images/20161209/20103434DyJrWV9GAB.png

重點就是使用eval.parentsubstitute函式


複習完了函式,突然點開Variable Explorer,發現了一個小地方:
R語言沒有宣告變數的概念,使用變數前不需要事先宣告型別也!

其實R和Python都屬於較鬆散型態的程式語言,相較C++、C#、Java、Swift等強調記憶體儲存空間、重視變數的生命週期有很大不同。

因為昨天沒關電腦,我們點開變數視窗查看:
昨天Day07.R 範例程式碼中的變數都還在!
http://ithelp.ithome.com.tw/upload/images/20161209/20103434ZAKFOpdBjc.png

如果想要清除所有變數,執行以下R Script就可以了

rm(list = ls()) 

http://ithelp.ithome.com.tw/upload/images/20161209/20103434nqtipvI4r7.png


A Big Function:Emirates A380

http://ithelp.ithome.com.tw/upload/images/20161208/20103434kX4FiDQCGP.png

2015-10 攝於巴塞隆納機場,加泰隆尼亞(spain)


上一篇
Day07 R語言的流程控制(loop)
下一篇
Day09 R語言的資料型別(Type)
系列文
R語言與機器學習見面會30

尚未有邦友留言

立即登入留言