R語言編程藝術(3)R語言編程基礎

本文對應《R語言編程藝術》

第7章:R語言編程結構;

第9章:面向對象的編程;

第13章:調試

?

=========================================================================

R語言編程結構

控制語句:

循環:

for (n in x) { }
while (condition) { }
repeat { }

  


另外break也可以用在另兩種形式的循環語句中。注意repeat沒有跳出循環的判斷條件,因此使用break(或者類似return())的語句。

除此之外,next語句可以用來跳過本次迭代的剩余部分。具體應用情景,是可以替代循環中的條件嵌套語句,不致代碼看起來混亂。

需要注意的是,for結構可以用在任何向量上,無論向量是什么模式,注意靈活運用。

?

對非向量集合的循環:R并不支持直接對非向量集合的循環,但是有一些間接但簡單的方式可以做到這點:

使用lapply()。如果循環的每次迭代之間相互獨立,就是用lapply(),可以允許以任意順序執行;

使用get()。這個函數接受一個代表對象名字的字符串參數,然后返回該對象的內容,看起來簡單,但是十分有用。

#假設u, v都是兩列的矩陣,要分別在這兩個矩陣上應用lm函數
for (m in c(“u”, “v”)) {
z <- get(m)
print(lm(z[, 2] ~ z[, 1]))
}

  

if-else結構:?

#注意以下代碼
if (r == 4) {x <- 1
} else {x <- 3y <- 4
}

  

雖然if后面只有一條語句,但是它對應的大括號是不能省略的,原因在于R的解釋器是根據else前面的右括號判斷這是一個if-else結構,如果沒有大括號,R將認為這是一個if結構。

#if-else結構的簡化
v <- if (cond) expression1 else expression2

  

這是一個簡化代碼的技巧,因為if-else結構最終會返回的值取決于cond是否為真。如果expression是函數調用語句,可以讓代碼更為清晰,但是如果語句復雜,就要優先考慮代碼是否清晰易懂。

處理向量時,使用向量化的ifelse()函數有可能提高運行速度。

?

?

算術和邏輯運算符及數值:

之前提到,R中只有向量,沒有標量,標量可以看作是僅有一個值的向量。但是在邏輯運算時,特別是if語句的條件控制,其邏輯值不能為向量,只能有一個值,也就是可以看作標量。這時,就要區分邏輯與和邏輯或的向量標量運算了。

x && y

標量的邏輯與運算

x || y

標量的邏輯或運算

x & y

向量的邏輯與運算

x | y

向量的邏輯或運算

如果if語句里的控制條件里出現向量并且長度大于1,R的處理方式是將向量的第一個元素作為控制條件返回結果,然后提示warning message

?

?

參數的默認值:

具名實參(named argument):如果不使用默認值,那么在調用函數時必須給出參數的具體名稱;

惰性求值(lazy evaluation)原則:除非有需要,否則不會計算一個表達式的值,也就是說具名實參不一定會被使用。

?

?

返回值:

函數的返回值可以是任何R對象。通常為列表形式,但是如果有需要,甚至可以返回另一個函數。

一般來說,如果只在函數結尾返回值,要避免顯式地調用return()函數。如果想要將程序表達得更加清晰,在函數中間部分返回值的時候可以顯式地調用return()函數。

返回復雜對象:函數的返回值可以是另一個函數。如果函數需要返回多個返回值,可以把它們儲存在一個列表或其他容器變量中。

?

?

函數都是對象:

注意到函數是對象,也就是說對于對象的操作對函數也適用。包括創建、編輯,甚至在以函數組成的列表上做循環。

g <- function(h, a, b) h(a, b)
body(g) <- quote(2 * x + 3)
g(3)  # 9

  


首先,function函數創建了一個函數,并賦值給g;然后body函數修改了g的函數體。因為函數主體部分屬于”call”類,而這種類是由quote()函數生成。

?

環境和變量作用域的問題:

頂層環境:<environment: R_GlobalEnv>

變量作用域的層次:里層的函數可以使用更加頂層的變量,如果層次之間變量命名發生沖突,優先使用最里層的變量。一般來說,里層對于更加頂層的變量只讀不可寫。可寫的情況將單獨討論。

ls()函數:調用不帶參數的ls()可以返回當前的局部變量;使用envir參數可以返回函數調用鏈中任何一個框架的局部變量名。

函數代碼對于其非局部變量一般只讀不寫,即使重新賦值也是影響它們的備份而不是變量本身。事實上,直到局部變量發生變化前,與其對應的全局變量是共享一個內存地址的。

?

?

R語言中沒有指針:

不能直接改變一個函數的參數,只能重新賦值。

其他因為沒有指針造成的問題將在下文討論。

?

?

向上級層次進行寫操作:

利用超賦值運算符對非局部變量進行寫操作:<<-

注意,超賦值運算符進行寫操作的時候,首先逐層向上級環境層次查找,遇到該變量的第一個層次即進行操作,如果沒有遇到,將在全局層次上新建變量。

用assign()函數對非局部變量進行寫操作:

可以通過設置函數參數指定向上層的哪一層次的變量進行寫操作。注意引用變量是使用字符串實現的。

全局變量的使用:一般來說不推薦在函數中寫全局變量,但是有時為了簡化代碼,這么做也是可以的,靈活運用即可。對于大型程序不推薦這樣做,因為存在著重寫不相關卻同名變量的風險。一種折中的方案是,在頂層環境中新建一個封裝全局變量的包,再使用assign()和get()函數通過索引到這個包來訪問全局變量。

閉包:這里的閉包指一種編程方法,具體做法是,先定義一個可創建局部變量的函數,再創建另一個函數可以訪問該變量。這樣,后面的一些函數創建的局部變量之間互不影響,各自獨立。

?

?

遞歸:

用于回歸和分類的遞歸分塊方法庫:rpart

?

?

置換函數:

任何左邊不是標識符(意味變量名)的賦值語句都可看作是“置換函數”。當遇到以下形式:

g(u) <- v

  

R語言會嘗試用以下方式執行:

u <- “g<-”(u, value = v)

  

直觀感受下,就是將值賦值給函數調用的結果。事實上,只要左邊不是變量名,就是一個置換語句,比如u[2] <- 8

?

?

寫函數代碼的工具:

快速載入環境:

?

source(“filename.R”)

  

?編輯函數:

f1 <- edit(f1)
f2 <- edit(f1)

  

?

創建自己的二元運算符:

> “%a2b%” <- function(a, b) return(a + 2 * b)
> 3 %a2b% 5
[1]  13

  

??

匿名函數:

如果函數不是很復雜,可以省去函數定義的過程,在使用function()命令建立函數后直接調用,因為沒有具體的函數名,因此稱為匿名函數。應用情況取決于具體情況,可以使代碼更加易讀緊湊。

?

?

=========================================================================

面向對象的編程

  1. 能接觸到的R中所有東西(從數字到字符串到矩陣)都是對象
  2. R支持“封裝”(encapsulation),即把獨立但相關的數據項目打包為一個類的實例。封裝可以幫助你跟蹤相關的變量,提高清晰度
  3. R類是“多態”(polymorphic)的,這意味著相同的函數使用不同類的對象時可以調用不同的操作。多態可以促進代碼可重用性
  4. R允許“繼承”,即允許把一個給定的類的性質自動賦予為其下屬的更特殊化的類

?

?

S3類:

一個S3類包含一個列表,再附加上一個類名屬性和調度(dispatch)的功能。

?

S3泛型函數:即同一個函數可以針對不同的類調用不同的操作。可以通過method()函數找到給定泛型函數的所有實現方法,返回值中,星號標注的是不可見函數(nonvisible function),即不在默認命名空間中的函數,可以通過getAnywhere()函數找到這些函數。另外可以查看一個類能應用的所有泛型函數,代碼method(, class = “classname”)

?

編寫S3類:“類”屬性可以通過attr()或class()函數手動設置。然后可以針對自己編寫的類,設定獨有的泛型函數,下面是一個例子:

#創建一個名為employee的類的對象
j <- list(name = “Joe”, salary = 55000, union = T)
class(j) <- “employee”
#編寫類employee的打印方法
print.employee <- function(wrkr) {cat(wrkr$name, “\n”)cat(“salary”, wrkr$salary, “\n”)cat(“union member”, wrkr$union, “\n”)
}

  


使用繼承:繼承的思想是在已有類的基礎上創建新的類:?

#創建類employee的子類hrlyemployee
k <- list(name = “Kate”, salary = 68000, union = F, hrsthismonth = 2)
class(k) <- c(“hrlyemployee”, “employee”)

  


新類包含了兩個字符串,分別代表新類和原有的類,新類繼承了原有類的方法,可以使用對應的泛型函數。泛型函數在調度時的工作原理是首先查找兩個類名稱的第一個,如果沒查到,則再去查找第二個類,實現了繼承。

?

S4類:

操作

S3類

S4類

定義類

在構造函數的代碼中隱式定義

setClass()

創建對象

創建列表,設置類屬性

new()

引用成員變量

$

@

實現泛型函數f()

定義f.classname()

setMethod()

聲明泛型函數

UseMethod()

setGeneric()

?

編寫S4類:

> #定義類employee
> setClass(“employee”,
+   representation(
+     name = “character”,
+     salary = “numeric”,
+     union = “logical”)
+ )[1] “employee”> #創建一個類的實例
> joe <- new(“employee”, name = “Joe”, salary = 55000, union = TRUE)
> joeAn object of class “employee”Slot “name”:[1] “Joe”Slot “salary”:[1] 55000Slot “union”:[1] TRUE> #引用成員變量
> joe@salary[1] 55000> slot(joe, “salary”)[1] 55000> #賦值也可以使用這兩種方法
> joe@salary <- 88000
> slot(joe, “salary”) <- 88000

  

S4類的安全性在于,如果給不存在的成員變量賦值,會有報錯消息,而S3類將會新建一個成員變量。

> joe@salry <- 48000Error in checkSlotAssignment(object, name, value) :“salry” is not a slot in class “employee”

  

在S4類上實現泛型函數:

#show()函數指在交互模式下,輸入變量名直接打印
setMethod(“show”, “employee”,
function(object) {inorout <- ifelse(object@union, “is”, “is not”)cat(object@name, “has a salary of”, object@salary,"and", inorout, "in the union", "\n")
}
)

  

S3類和S4類的對比:

S3具有較強的靈活性,而S4具有很好的安全性。一般來說推薦使用S3使代碼更加靈活,而當安全性更加重要時選擇S4(比如混合編程的情況下)。

?

?

對象的管理:

ls()函數:列出所有對象;

rm()函數:刪除特定對象;

save()函數:保存對象集合,可以用load()載入;

查看對象內部結構的函數:class(), mode(), names(), attributes(), unclass(), str(), edit();

exists()函數:判斷對象是否存在。

?

?

=========================================================================

調試

調試的基本原則:

調試的本質:確認原則;

從小處著手;

模塊化的、自頂向下的調試風格;

反漏洞。

?

轉載于:https://www.cnblogs.com/gyjerry/p/6530099.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/259428.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/259428.shtml
英文地址,請注明出處:http://en.pswp.cn/news/259428.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

用C++流成員函數put輸出單個字符

轉載&#xff1a;http://c.biancheng.net/cpp/biancheng/view/254.html 在程序中一般用cout和插入運算符“<<”實現輸出&#xff0c;cout流在內存中有相應的緩沖區。有時用戶還有特殊的輸出要求&#xff0c;例如只輸出一個字符。ostream類除了提供上面介紹過的用于格式控…

linux 擴充db2表空間,如何擴充db2的表空間、加容器等表空間維護操作

db2 "alter tablespace GJDATA resize (FILE /backup/GJDATA32K45G)"db2 "alter tablespace GJIDX resize (FILE /backup/GJIDX32K45G)"容器路徑 db2 list tablespace containers for8容器大小 db2pd -d uibsch -tablespaces降低容器空間 resize 增加容器…

CheckBox控件

前臺代碼&#xff1a; 1 <asp:CheckBox ID"CheckBox1" runat"server" Text "蘋果"/> 2 <asp:CheckBox ID"CheckBox2" runat"server" Text "檸檬"/> 3 <asp:CheckBox ID"CheckBox3" runa…

.NET垃圾回收筆記

名詞 垃圾收集目標 ephemeral GC發生在Gen 0 和Gen 1 的垃圾收集 Full GC發生Gen 2 及以上的Gen與LOH的垃圾收集 垃圾收集模式 工作站模式GC直接發生在內存分配的線程&#xff08;也是當前的工作托管線程&#xff09;上 服務器模式每個CPU核都有一個自己獨立的GC線程與托管堆 垃…

go.js中的圖標(icons)的使用

2019獨角獸企業重金招聘Python工程師標準>>> 1、圖標庫下載&#xff1a; 將icons引入&#xff1a;http://gojs.net/latest/samples/icons.js 2、樣式演示 地址&#xff1a;http://gojs.net/latest/samples/icons.html 轉載于:https://my.oschina.net/u/2391658/blog…

Pygame - Python游戲編程入門(1)

前言 在上一篇中&#xff0c;我們初步熟悉了pygame的控制流程&#xff0c;但這對于一個游戲而言是遠遠不夠的。所以在這一篇中&#xff0c;我們的任務是添加一架飛機&#xff08;玩家&#xff09;&#xff0c;并且能夠控制它進行移動&#xff0c;這樣我們就又離目標進了一步了~…

C++字符輸入getchar()和字符輸出putchar()

轉載&#xff1a;http://c.biancheng.net/cpp/biancheng/view/117.html C還保留了C語言中用于輸入和輸出單個字符的函數&#xff0c;使用很方便。其中最常用的有getchar函數和putchar函數。 putchar函數(字符輸出函數) putchar函數的作用是向終端輸出一個字符。例如&#xf…

linux實現shell,linux

4.5Mhttp://www.starbase-929.net/media/Calibre%20Library/Ken%20O.%20Bartch/Linux%20Shell%20Scription%20With%20Bash%20(1778)/Linux%20Shell%20Scription%20With%20Bash%20-%20Ken%20O.%20Bartch.pdfstarbase-929.net全網免費4.0Mhttp://www.myaitcampus.net/elibrary/im…

AQS淺析

2019獨角獸企業重金招聘Python工程師標準>>> AQS的原理淺析 本文是《Java特種兵》的樣章&#xff0c;本書即將由工業出版社出版 AQS的全稱為&#xff08;AbstractQueuedSynchronizer&#xff09;&#xff0c;這個類也是在java.util.concurrent.locks下面。這個類似乎…

str045漏洞提權linux,Linux運維知識之CVE-2016-5195 Dirtycow: Linux內核提權漏洞

本文主要向大家介Linux運維知識之CVE-2016-5195 Dirtycow&#xff1a; Linux內核提權漏洞紹了&#xff0c;通過具體的內容向大家展現&#xff0c;希望對大家學習Linux運維知識有所幫助。CVE-2016-5195 Dirtycow&#xff1a; Linux內核提權漏洞以下都是github上找的源碼&#xf…

編程如寫作

昨晚似乎是個適合寫作的夜&#xff0c;不論是自己還是朋友&#xff0c;都比平常更容易被觸動。看著微博上朋友們的心路&#xff0c;想寫點什么卻似乎找不出非常值得大書特書的主題&#xff0c;只是歪坐在電腦旁&#xff0c;喝著咖啡&#xff0c;單曲循環著倉木麻衣的《time aft…

C++中cin、cin.get()、cin.getline()、getline()等函數的用法

轉載&#xff1a;http://www.cnblogs.com/flatfoosie/archive/2010/12/22/1914055.html c輸入流函數主要以下幾個&#xff1a; 1、cin 2、cin.get() 3、cin.getline() 4、getline() 附:cin.ignore();cin.get()//跳過一個字符,例如不想要的回車,空格等字符 1、cin>>…

工作環境總結(1)開發環境搭建

1、安裝git 安裝文件&#xff1a;Git-2.12.0-64-bit.exe 下載地址&#xff1a;https://github.com/git-for-windows/git/releases/download/v2.12.0.windows.1/Git-2.12.0-64-bit.exe 在git bash中配置&#xff0c;git bash命令行中執行&#xff08;只有使用到egit時使用&…

c語言煙花百度云,C語言實現放煙花的程序

這是一個利用C語言編寫放煙花的程序(同時也可以播放音樂)&#xff0c;供大家參考&#xff0c;具體內容如下代碼如下#pragma once#include#include //圖形界面庫頭文件#include //計算圓形的軌跡坐標#include#include#include#include#pragma comment(lib,"winmm.lib"…

決定人生的七條公式

1 .積跬步以致千里&#xff0c;積怠惰以致深淵 1.01^365 37.80.99^365 0.032.拖延癥 U EV/ID U完成任務的程度 E對成功的信心 V 對任務的愉悅度 I 你的分心程度 D你多久會獲得回報3.三天打魚兩天曬網&#xff0c;終將一無所獲 1.01^3 x 0.99^2 < 1.01 4.愛因斯坦的成…

strncpy與strcpy的區別與注意事項

strncpy 是 C語言的庫函數之一&#xff0c;來自 C語言標準庫&#xff0c;定義于 string.h&#xff0c;char *strncpy(char *dest, char *src, int n)&#xff0c;把src所指字符串的前n個字節復制到dest所指的數組中&#xff0c;并返回指向dest的指針。 strcpy只是復制字符串&am…

使用ssh公鑰實現免密碼登錄

ssh 無密碼登錄要使用公鑰與私鑰。linux下可以用用ssh-keygen生成公鑰/私鑰對&#xff0c;下面我以CentOS為例。 有機器A(192.168.1.155)&#xff0c;B(192.168.1.181)。現想A通過ssh免密碼登錄到B。 首先以root賬戶登陸為例。 1.在A機下生成公鑰/私鑰對。 [rootA ~]# ssh-keyg…

15款的視頻處理軟件免費下載

因為需要購買昂貴的視頻處理軟件和高性能圖形計算機&#xff0c;所以視頻處理是一項比較耗費金錢的技術活。正是由于這樣&#xff0c;一部分人選擇使用性能較好的免費在線編輯軟件&#xff0c;無需太多視頻處理知識便可在瀏覽器中剪切和編輯視頻。然而&#xff0c;當我們無法連…

液位系統c語言程序,超聲波自動測量物體液位系統的設計

超聲波自動測量物體液位系統的設計(任務書,畢業論文15000字)摘要本系統以STC89C52單片機為核心&#xff0c;通過硬件電路連接和軟件程序的編寫實現通用型超聲波自動測量物體液位系統的設計。其主要原理是由單片機控制超聲波發射電路發射超聲波&#xff0c;超聲波接收電路接收遇…

android-sdk-windows版本號下載

Android SDK 4.0.3 開發環境配置及執行 近期又裝了一次最新版本號的ADK環境 眼下最新版是Android SDK 4.0.3 本文的插圖和文本盡管是Android2.2的 步驟都是一樣的&#xff0c;假設安裝的過程中遇到什么問題&#xff0c;能夠留言&#xff0c;我會盡快回復&#xff01; 系統環境的…