解析哈囉世界
在約維安計畫:R 語言起步走我們透過 print("Hello, World!") 來
確認 R 語言的開發環境及執行環境是否已經安裝妥當,在這一段哈囉世界的程式碼中,其實就能體會我們在文章一開始引用 Greg Martin 對於 R 語言核心精神的詮釋:對資料結構應用函數。
The way R works is pretty straightforward, you apply functions to objects.
print
是函數的名稱,print()
則表示要應用該函數的功能,而 “Hello, World!“
則是一個被稱呼為文字(Character)的向量資料結構;換言之,哈囉世界可以表達為:對 “Hello, World!“
這個文字向量應用了 print()
函數。
print("Hello, World!")
## [1] "Hello, World!"
什麼是函數
函數是構成所有程式語言的基本要素,一個函數是一段「被命名」的程式碼,這段程式碼可以用於執行某個特定任務,可能是數值的運算或者文字的處理,當使用者想要應用(使用、呼叫)某一個函數之前,必須先確定在欲產生作用的範疇中該函數已經被定義或者被載入。簡而言之,在哈囉世界的程式碼中,之所以能夠對字串 “Hello, World!“
應用 print()
函數,是因為 print()
函數屬於 R 語言的內建函數,在 R 語言啟動的當下就會被載入供我們使用。
函數的來源
R 語言使用者除了能夠應用內建函數以外,還可以從其他兩個管道取得所需要的函數:
套件(Packages)。
自行定義。
僅有內建函數可以供我們直接使用,另外兩個管道的函數都必須在使用之前確定好在欲產生作用的範疇中已經被載入或者定義。使用套件中的函數之前,我們必須確認套件是否已經安裝、載入,使用自行定義的函數之前,則是必須確認該函數是否已經完成定義。載入套件的函數是 library()
。
library("package_name")
function_name()
我們短期還沒有要使用套件中的函數,不過倒是馬上會有自行定義函數的需求,自行定義函數需要考慮五個組成要件:
函數名稱。
輸入。
參數。
函數主體。
輸出。
看似抽象,不過想想平日購買珍珠鮮奶茶的流程,就像是函數的運作一般:
函數名稱:購買珍珠鮮奶茶。
輸入:中杯 35 元;大杯 50 元。
參數:甜度(無糖、微糖、半糖、少糖、全糖)與冰塊(去冰、少冰、全冰)。
函數主體:點餐、貼標籤、加珍珠、加冰塊、倒茶、加鮮奶一直到封口。
輸出:珍珠鮮奶茶。
function_name <- function(INPUTS, PARAMETERS){
# body of the function
# ...
# ...sequence of statements
return(OUTPUTS)
}
#
是用來標記註解的符號,有 #
標記的該行敘述將不會被 R 語言執行,這讓寫程式的人能夠用口語來描述這段程式的目的是什麼,如果將哈囉世界改寫為函數形式,每次只需要輸入函數名稱並加上小括號 hello_world()
,就可以獲得 “Hello, World!“
這個文字向量為輸出。
hello_world <- function(){
return("Hello, World!")
}
hello_world()
## [1] "Hello, World!"
建立物件
除了直接對 “Hello, World!“
文字向量應用 print()
函數,更常見的作法是將資料賦值給物件(Objects),然後再對物件應用函數,完整的說法為 a_character
物件是文字向量這個資料結構的實例(Instance)。
a_character <- "Hello, World!"
a_character
## [1] "Hello, World!"
在為物件取名稱的時候,應該要謹記四個原則:
命名的時候使用有意義的全小寫英文,採用蛇形命名法(Snake-case),不同單字之間以底線
_
相隔;或者採用駝峰命名法(Camel-case),不同單字之間以大寫區隔。例如a_character
或者aCharacter
使用
<-
而非=
作為賦值運算符。不可以使用保留字做為物件的命名,這樣做將會產生直譯錯誤。
不要使用內建函數做為物件的命名,這樣做將會覆蓋內建函數的功能。
其中 R 語言的保留字可以透過 help(reserved) 來查詢。
help(reserved)
## if else repeat while function for in next break
## TRUE FALSE NULL Inf NaN NA
## NA_integer_ NA_real_ NA_complex_ NA_character_
什麼是資料結構
在電腦科學中資料結構是用來儲存、組織以及存取數據的機制,資料科學家日常工作中大幅仰賴資料結構作為輸入、清理、轉換、分析與輸出數據的平台。R 語言與其他程式語言(例如 Python)最大的差異在於她省略了「資料類別」這個層級,直接以「資料結構」作為最基本的單位,這點是一個很大的不同。
R 語言最基本的資料結構是向量(vector
),由向量可以再組織、轉換為其他的資料結構,常用的六種基本資料結構有:
向量(
vector
)。矩陣(
matrix
)二維向量。陣列(
array
)n 維向量。因素向量(
factor
)具有整數編碼的文字向量。清單(
list
)一維異質向量。資料框(
data.frame
)二維異質向量。
而向量作為最基本的單位,還可以再細分為七種不同類型:
數值(
numeric
)。整數(
integer
)。文字(
character
)。邏輯(
logical
)。日期(
date
)。日期時間(
POSIXct
)。未定義值(
NA/NULL/NaN/-Inf/Inf
)。
由於常見對資料結構應用函數的時候,都是對建立完成的物件應用,而非直接對資料結構本身應用,這是因為程式設計通常在後續會有資料記錄與運算處理的需求,並不僅止與將其印出來而已。所以我們需要一個能夠將完成宣告的物件所儲存之資料結構告知使用者的內建函數,這個內建函數是 class()
或者 typeof(),作用是將被應用物件的資料結構回傳。
a_character <- "Hello, World!"
class(a_character)
## [1] "character"
typeof(a_character)
## [1] "character"
對資料結構應用函數的兩種語法
在 R 語言中對資料結構應用函數可以使用兩種語法:
function_name(object_name)
object_name PIPE OPERATOR function_name()
第一種是最為常見、也更為大眾接受的語法,函數名稱的小括號中輸入物件名稱。
a_character <- "Hello, World!"
print(a_character)
## [1] "Hello, World!"
第二種則是比較少見的語法,物件名稱後加入一個 PIPE OPERATOR
連結函數名稱的小括號。
a_character <- "Hello, World!"
a_character |> print()
## [1] "Hello, World!"
其中的 |>
就是所謂的 PIPE OPERATOR
,在 R4.1 以後的版本是內建的運算符號,如果是在 R4.1 以前的版本,就要使用 magrittr 套件給予的 %>% 作為 PIPE OPERATOR
# install.packages("magrittr")
library("magrittr")
a_character <- "Hello, World!"
a_character %>% print()
## [1] "Hello, World!"
在初步認識 R 語言的函數與資料結構之後,約維安計畫:對資料結構應用函數來到尾聲,希望您也和我一樣期待下一篇文章。
延伸閱讀
對於這篇文章有什麼想法呢?喜歡😻、留言🙋♂️或者分享🙌
計畫學員專區
付費訂閱電子報的會員可以點選 nbgitpuller 連結將本篇文章完整的 Jupyter Notebook 複製到自己的 Jupyter Server:
伺服器選項選擇預設的「Data science environment:學習 Python、R 與 Julia 的資料科學環境」就可以順利運作文章中的範例程式。
忘記了什麼是 Jupyter 星球嗎?複習一下約維安計畫:歡迎光臨 Jupyter 星球吧!