九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項超值服

開通VIP
R語言筆記6:在R中寫一些簡單的函數(shù)、functions基礎(chǔ)和作用域

R語言基礎(chǔ)系列:


Your first R function

命令一個函數(shù)時,一般不寫在交互式命令行里,而是寫在一個空白的文本文件中,即把函數(shù)放在一個R包中,這里面包含著文檔(documentation),是一個更加結(jié)構(gòu)化的環(huán)境。

我們使用的軟件是RStudio,左上角新建一個新的R腳本來寫代碼。

Example 1

舉個例子,簡單了解一下如何使用函數(shù)的語法、如何指定參數(shù)以及如何返回結(jié)果:

命令一個簡單的函數(shù),求x, y的和。

  1. ## 給函數(shù)賦值為add2,第一行小括號里寫進(jìn)變量,第二行大括號里寫入運(yùn)算

  2. add2 <> function(x, y) {

  3.  x + y

  4. }

  5. ## 因為R函數(shù)會返回最后一個表達(dá)式的值,所以不用寫返回

在控制臺(console)運(yùn)行腳本,賦值后即可得到結(jié)果:

  1. > add2 <> function(x, y) {

  2. +   x + y

  3. + }

  4. > add2(7, 5)

  5. [1] 12

Example 2

下一個例子稍微復(fù)雜一點:

我們要輸入一個數(shù)字向量,然后返回這個向量的子集(返回其中大于10的數(shù)字)

  1. above10 <> function(x){   ##  命名變量

  2.    use <> x > 10         ##  邏輯語句,來判斷變量x是否大于10

  3.    x[use]                ##  取子集

  4. }

運(yùn)行:

  1. > above10 <> function(x){

  2. +   use <> x > 10

  3. +   x[use]

  4. + }

  5. > x <> 1:16

  6. > above10(x)  

  7. [1] 11 12 13 14 15 16

  8. > above10(1:9)

  9. integer(0)

如果我們不設(shè)置10,而是改成任意數(shù)字n,以上命令可改寫為:

  1. above <> function(x, n){

  2.  use <> x > n

  3.  x[use]

  4. }

運(yùn)行:

  1. > above <> function(x, n){

  2. +   use <> x > n

  3. +   x[use]

  4. + }

  5. > x <> 1:16

  6. > above(x, 12)

  7. [1] 13 14 15 16

設(shè)置“缺省值”(可以理解為默認(rèn)值),即如果在函數(shù)運(yùn)行過程中不指定n的值時,系統(tǒng)自動篩選的標(biāo)準(zhǔn):

  1. above <> function(x, n = 10){   ## 設(shè)置缺省值為10

  2.  use <> x > n

  3.  x[use]

  4. }

這時當(dāng)你運(yùn)行函數(shù)時:

  1. > above <> function(x, n = 10){

  2. +   use <> x > n

  3. +   x[use]

  4. + }

  5. > above(x)     ## 自動篩選數(shù)字向量中大于10的數(shù)字

  6. [1] 11 12 13 14 15 16

Example 3

下面這個例子再復(fù)雜一點,我們要給函數(shù)一個參數(shù),然后使用循環(huán)遍歷這個函數(shù)的每一列:

比如,取一個矩陣,然后計算每列的平均值:

  1. columnmean <> function(x){   ## 給函數(shù)命名,設(shè)置參數(shù)x,用于儲存矩陣

  2.  nc <> ncol(x)              ## 計算矩陣中有多少列

  3.  means <> numeric(nc)       ## 設(shè)置數(shù)值向量儲存列數(shù),長度等于列數(shù),它是一個空向量,每個元素的初始值為0,數(shù)值在循環(huán)中填滿。

  4.  for (i in 1:nc){           ## 設(shè)置循環(huán),循環(huán)參數(shù)在整數(shù)向量1到列數(shù)之間

  5.    means[i] <> mean(x[,i])  ## 把每一列的平均值賦予means[i],x[,i]是矩陣取子集,即求每列的平均值

  6.  }

  7.  means                 ## 返回means,平均值向量

  8. }

運(yùn)行這個程序,計算 airquality數(shù)據(jù)集每列的平均值:

ps. airquality數(shù)據(jù)集有6列,前六行長這樣:

  1. > head(airquality)

  2.  Ozone Solar.R Wind Temp Month Day

  3. 1    41     190  7.4   67     5   1

  4. 2    36     118  8.0   72     5   2

  5. 3    12     149 12.6   74     5   3

  6. 4    18     313 11.5   62     5   4

  7. 5    NA      NA 14.3   56     5   5

  8. 6    28      NA 14.9   66     5   6

運(yùn)行腳本可以看到函數(shù) columnmean(airquality)返回了6個平均值:

  1. > columnmean <> function(x){

  2. +   nc <> ncol(x)

  3. +   means <> numeric(nc)

  4. +   for (i in 1:nc){

  5. +     means[i] <> mean(x[,i])

  6. +   }

  7. +   means

  8. + }

  9. > columnmean(airquality)

  10. [1]        NA        NA  9.957516 77.882353  6.993464 15.803922

可以看到,如果某列有缺失值NA的話,計算得出的數(shù)值就直接是NA。

所以我們可以添加一個邏輯參數(shù),設(shè)置移除缺失值:

  1. columnmean <> function(x, removeNA = TRUE){   ## 添加參數(shù),并設(shè)置缺省值為TRUE

  2.  nc <> ncol(x)

  3.  means <> numeric(nc)

  4.  for (i in 1:nc){

  5.    means[i] <> mean(x[,i], na.rm = removeNA)   ## 在mean()函數(shù)中添加參數(shù)

  6.  }

  7.  means

  8. }

再次運(yùn)行程序,可以看到計算結(jié)果是默認(rèn)移除NA后求得的平均值:

  1. > columnmean(airquality)

  2. [1]  42.129310 185.931507   9.957516  77.882353   6.993464  15.803922

Functions in R

主要分三個部分來講解函數(shù):

  • 編寫函數(shù)所需的基礎(chǔ)知識

  • 相關(guān)語法作用域

  • R語言作用域的規(guī)則

編寫函數(shù)所需的基礎(chǔ)知識

R語言通過 function()指令來命名和創(chuàng)建函數(shù)。首先要給函數(shù)賦值,也就是命名,然后在小括號中寫入?yún)?shù),最后再大括號中寫入函數(shù)要執(zhí)行的語句,其基本語法是:

  1. f <> function(arguments>){

  2.    ## Do something interesting

  3. }

同時在R中,你可以將函數(shù)作為參數(shù)傳遞給其他函數(shù),即嵌套。

函數(shù)的返回值是函數(shù)執(zhí)行部分中的最后一行表達(dá)式。

編寫函數(shù)的過程中我們可以設(shè)置和命名參數(shù),這些參數(shù)可以代表數(shù)值、矩陣、數(shù)據(jù)框或邏輯值等等。同時也可以設(shè)置一些具有缺省值(默認(rèn)值)的參數(shù)。

  • 形式參數(shù)(formal arguments)

形式參數(shù)是包含在函數(shù)定義里的參數(shù)。

formals()會將一個函數(shù)作為輸入(input),并返回函數(shù)所有的形式參數(shù)組成的列表。

在R中,不是所有命令都用到所用的形式參數(shù)。加入一個函數(shù)中設(shè)置了10個參數(shù),但我們往往并不需要指定每個參數(shù)的值是啥,所以函數(shù)可以缺失某些參數(shù)。當(dāng)沒有明確賦值是,它的取值就是缺省值(默認(rèn)值,default value)

  • 匹配參數(shù)(argument matching)

可以根據(jù)位置或名稱來匹配函數(shù)參數(shù),這是編寫和調(diào)用函數(shù)的關(guān)鍵。

以計算數(shù)據(jù)標(biāo)準(zhǔn)差的函數(shù) sd()為例。

  1. > data <> rnorm(100)    ## 取100個符合正態(tài)分布的隨機(jī)數(shù)

  2. > sd(x = data)          ## 給參數(shù)賦值 求標(biāo)準(zhǔn)差

  3. [1] 1.035329

  4. > sd(data)              ## 給參數(shù)默認(rèn)賦值

  5. [1] 1.035329

  6. > sd(data, na.rm = FALSE)

  7. [1] 1.035329

  8. > sd(na.rm = FALSE, data)  ## 調(diào)換參數(shù)位置后結(jié)果不變

  9. [1] 1.035329

以上所有表達(dá)式都是等價的,但是最好不要調(diào)換參數(shù)位置。

如果函數(shù)中參數(shù)較多,那么最好使用位置匹配。

比如 lm()函數(shù)(把數(shù)據(jù)擬合到線性模型),它的參數(shù)列表這么長:

  1. > args(lm)

  2. function (formula, data, subset, weights, na.action, method = 'qr',

  3.    model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE,

  4.    contrasts = NULL, offset, ...)

  5. NULL

前五個參數(shù)都沒有缺省值,依次是,公式、數(shù)據(jù)、子集、權(quán)重等。這里使用者必須要指定他們的值。

  1. lm(y ~ x, mydata, 1:100, model = FALSE)

大多數(shù)情況下,我們不知道參數(shù)的具體位置,所以在命令行中,命名參數(shù)來匹配最安全。

The order of operations when given an argument is:

  1. Check for exact match for a named argument

  2. Check for a partial match

  3. Check for a positional match

  • 惰性求值(Lazy Evaluation)

惰性求值是R語言的一個關(guān)鍵特性,也是許多編程語言常用的模型。僅在使用函數(shù)參數(shù)時對其求值。

第一個例子:

  1. > f <> function(a, b) {

  2. +         a^2

  3. + }

  4. > f(2)

  5. [1] 4

這里定義函數(shù)f,有兩個參數(shù),但返回值僅僅是a的平方。所以當(dāng)運(yùn)行f(2)時,和b無關(guān),所以系統(tǒng)自動跳過,不會報錯。

第二個例子:

  1. > f <> function(a, b) {

  2. +         print(a)

  3. +         print(b)

  4. + }

  5. > f(45)

  6. [1] 45

  7. Error in print(b): argument 'b' is missing, with no default

這里同樣定義f有兩個參數(shù),但返回值是a和b,所以當(dāng)輸入f(45)時,因為第二個位置上缺少b的賦值,所以會報錯。這里就是用了惰性求值,即,僅在使用這個參數(shù)的時候進(jìn)行求值,在這之前的程序都是有效的并可以執(zhí)行,直至運(yùn)行到出錯的部分。

  • 特殊參數(shù) ...

...參數(shù)是一種特殊的參數(shù),表明一些可以傳遞給另一個函數(shù)的參數(shù)。常用于當(dāng)你需要擴(kuò)展另一個函數(shù),而你又不想復(fù)制原函數(shù)的整個參數(shù)列表時。

如下例,你希望修改 plot()函數(shù)中的個別參數(shù),而其他參數(shù)保持不變,將其應(yīng)用于一個新定義的函數(shù)中 myplot()

  1. myplot <> function(x, y, type = 'l', ...) {

  2.        plot(x, y, type = type, ...)         ## Pass '...' to 'plot' function

  3. }

在泛型函數(shù)(generic function)中, ...還有另一種用法,它的作用是根據(jù)數(shù)據(jù)類型使用合適的方法

泛型函數(shù)是一個函數(shù)族,其中的每個函數(shù)都有相似的功能,但是適用于某個特定的類。

  1. > mean

  2. function (x, ...)

  3. UseMethod('mean')

  4. bytecode: 0x5d5e3e8>

  5. environment: namespace:base>

還有一種情況下, ...參數(shù)必須使用:

那就是,當(dāng)傳遞到函數(shù)的參數(shù)數(shù)量不能事先確定的時候。

比如 paste()函數(shù),他的作用是將一連串字符串連接起來,然后新建一個字符串或向量,所以無法預(yù)知參數(shù)個數(shù):

  1. > args(paste)

  2. function (..., sep = ' ', collapse = NULL)

  3. NULL

還有 cat()函數(shù),它的功能是和 paste相似,也是連接字符串。

  1. > args(cat)

  2. function (..., file = '', sep = ' ', fill = FALSE, labels = NULL,

  3.    append = FALSE)

  4. NULL

使用 ...函數(shù)的一個注意事項:

就是任何出現(xiàn)在 ...之后的參數(shù)列表必須明確的給出名稱。而且不能夠部分匹配或位置匹配

舉例:

  1. > paste('a','b',sep = ':')

  2. [1] 'a:b'

不能位置匹配或部分匹配:

  1. > paste('a','b',':')

  2. [1] 'a b :'

  3. > paste('a','b',se = ':')

  4. [1] 'a b :'

Scoping Rules of R

作用域(scope,或譯作有效范圍)是名字(name)與實體(entity)的綁定(binding)保持有效的那部分計算機(jī)程序。

什么是作用域規(guī)則?

作用域規(guī)則(Scoping Rules)決定了一個函數(shù)的值如何與自變量綁定起來

在一個函數(shù)中,有兩種類型的變量:

一種是函數(shù)的參數(shù),

另一種存在于函數(shù)中的其他變量或符號,并非是函數(shù)的參數(shù)。問題在于你如何給這些符號賦值。

R用的是詞法作用域(Lexical Scoping),也成靜態(tài)作用域。

詞法作用域又叫做靜態(tài)作用域,采用詞法作用域的變量叫詞法變量。

詞法作用域里,取變量的值時,會檢查函數(shù)定義時的文本環(huán)境,捕捉函數(shù)定義時對該變量的綁定。

詞法變量有一個在編譯時靜態(tài)確定的作用域。詞法變量的作用域可以是一個函數(shù)或一段代碼,該變量在這段代碼區(qū)域內(nèi)可見(visibility);在這段區(qū)域以外該變量不可見(或無法訪問)。

相反,采用動態(tài)作用域的變量叫做動態(tài)變量。

只要程序正在執(zhí)行定義了動態(tài)變量的代碼段,那么在這段時間內(nèi),該變量一直存在;代碼段執(zhí)行結(jié)束,該變量便消失。

詞法作用域的優(yōu)點是能夠簡化運(yùn)算,在統(tǒng)計分析時非常有效

通過下面這個函數(shù),舉個栗子:

f <- function(x,="" y)="" {=""  x^2="" +="" y="">

這個函數(shù)是取x的平方然后加上y除以z的值,其中有兩個明確的形式參數(shù)xy,問題是z從哪兒來的?

因為沒有在函數(shù)中定義z,所以z是一個自由變量。

語法作用域解決的問題就是怎樣給一個類似z的自由變量賦值


詞法作用域的規(guī)則

詞法作用域的規(guī)則,簡而言之一句話:

在定義函數(shù)的環(huán)境中搜索自由變量的值。

那么問題來了……

什么是環(huán)境?

環(huán)境是符號-值對(symbol-value,如x = 3.14)的集合。每一個符號都有一個與之綁定的值。

每個環(huán)境都有一個上層環(huán)境(parent environment)。對于上層環(huán)境而言,他可能有很多子環(huán)境。唯一沒有上層環(huán)境的環(huán)境叫做空環(huán)境。

你可以把你的全局環(huán)境(工作空間)看做一系列“符號-值對”,其中每個對象都有一個與之關(guān)聯(lián)的對象。

因此,每一個包都有一個命名空間,就是一個環(huán)境,其中有很多符號、以及與符號關(guān)聯(lián)的值。

如果你把一個函數(shù)和環(huán)境聯(lián)系起來,就創(chuàng)建了一個閉包(function losure),這些閉包是R中各種各樣神器操作的關(guān)鍵所在。


所以,如果要在函數(shù)里遇到自由變量,怎么辦?

先你需要找的是:這個函數(shù)是在那個環(huán)境中被定義的??纯词欠裨谌汁h(huán)境中被定義,如果沒有,就去它的父環(huán)境里面找,以此類推,往上找直到頂層環(huán)境。(在全局環(huán)境外定義函數(shù)也是有可能的)

如果所有環(huán)境中都找不到想要的符號的話,就會報錯。


作用域規(guī)則的重要性

為什么作用域規(guī)則很重要?

通常在全局環(huán)境重定義一個函數(shù),在工作區(qū)就能夠找到自由變量的值。

但是重點是,在R中,你能夠在函數(shù)里面再定義其他函數(shù)。

一般情況下,函數(shù)的返回值是數(shù)值、數(shù)據(jù)框、列表、等等,但也有可能是一個函數(shù)。

在這種情況下,全局環(huán)境就產(chǎn)生了變化,作用域原則的影響就表現(xiàn)出來了。

舉例,定義一個“構(gòu)造性”函數(shù),即這個函數(shù)在構(gòu)造另一個函數(shù):

make.power <- function(n)="" {=""  pow=""><- function(x){=""  =""  x^n=""  }="">

創(chuàng)建一個構(gòu)造函數(shù)mmake.power(),賦值為n;其內(nèi)部用來構(gòu)造另一個函數(shù)pow(),賦值為x。這個函數(shù)的功能是,pow()對它的參數(shù)x求n次方,然后make.power()返回結(jié)果。

所以在函數(shù)pow()的內(nèi)部,x是參數(shù),n就是一個自由變量。

所以如果運(yùn)行函數(shù)make.power,賦值給cube,那么cube就會返回一個函數(shù):

> cube <- make.power(3)=""> cubefunction(x){    x^n  }

這時,cube就成了一個函數(shù)cube(),相當(dāng)于pow()(實際上是沒有pow的,他只是一個內(nèi)部的代號),所以調(diào)用cube()

> cube(2)[1] 8

(2的立方是8)


Exploring a Function Closure

怎么才能查看一個函數(shù)所在的環(huán)境中都有啥?

調(diào)用ls函數(shù)

如上例:

> ls(environment(cute))[1] 'n'   'pow'

查看對象的賦值,使用get()

> get('n', environment(cute))[1] 3

這就是cute()怎么知道n=3的過程。


參考資料:

  1. 視頻課程 R Programming by Johns Hopkins University:https://www.coursera.org/learn/r-programming/home/welcome

  2. 講義 Programming for Data Science :https://bookdown.org/rdpeng/rprogdatascience/R

-------------------我是求關(guān)注的分界線--------------

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Python之函數(shù)的定義與使用示例
JavaScript 新手的踩坑日記
從 JavaScript 作用域說開去
JavaScript變量作用域之殤
(12) javascript中var、let、const聲明的區(qū)別
搞懂JavaScript引擎運(yùn)行原理
更多類似文章 >>
生活服務(wù)
熱點新聞
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服