1. 程式人生 > >R語言-基本資料結構的用法

R語言-基本資料結構的用法

關鍵詞:向量、矩陣、陣列、資料框、因子、列表


近期開始上手R語言,可能是出於對機器學習的興趣吧從而瞭解到這門語言;

之前也看過人生苦短的Python,當然這兩門語言都是人工智慧技術中很好的工具;

二者也存在一些相同之處,當然是除了開源之外的一些相同之處;

本人蔘考的書籍是R語言實戰[Robert I. Kabacoff]撰寫的


1、向量

有的書籍上說向量是R語言最基本的資料型別,我覺得還是很有道理的,即使是初學者,從後面的幾個資料型別也能看出這裡面的深意。如果你還記得學校裡面學過的線性代數這門課,並且有幸還記得向量的數學定義,那麼向量,包括後面的幾個資料型別,你理解起來會很舒服。

在R裡面向量是儲存數值型、字元型或邏輯型資料的一維陣列(注意和後面的陣列型別對比反思)。簡單來說,向量裡面的資料只允許是同一種類型,與MATLAB不同,R裡面的向量建立語句如下:

a <- c(1, 2, 3, 4, 5)
b <- c("a", "b", "c")
c <- c(TRUE, FALSE, FALSE)

順帶回顧一下,R裡面的賦值符號是“<-”或者“->”,操作順序與箭頭方向一樣,當然“=”也能用,故以下程式碼基本等價:

a <- 3
3 -> a
a = 3

大佬告訴我,R裡面少用“=”,有時候會出現問題,甚至會被同行取笑。真的是拋bug又丟人,留意。

在生成第一個向量a的時候,你會發現這個向量的元素的連續的數值型資料,如果你是聰明人的話肯定不會在面臨需要用一個向量儲存1-50的時候一個一個字地敲。測試下面的程式碼,你會發現a和b沒什麼區別

a <- c(1, 2, 3, 4, 5)
b <- c(1 : 5)
c <- c(5 : 1)
既然都有(1:5)了,何不試試(5:1)呢,而且有時候可能也很方便,正如上面c所做到的一樣。

上文說過向量是最基本的資料型別,因為單個常量其實可以看做只有一個元素的向量,又叫標量,這和其他高階語言類似:

pi <- 3.14
today <- "2018/4/27"
ChinaNumberOne <- TRUE

如何訪問向量的元素呢?正如你曾在學習java或者C的時候也想過的那樣。

這裡的方法會清新得讓你歡呼,因為從訪問單個元素的格式上看和java他們沒什麼區別,但訪問多個元素的時候更是讓你覺得很歡快。


正如你所看到的,這裡潛藏著對非計算機職業人員的業餘愛好者一個非常好理解的特性:R語言裡面的first one是1,而不是從0開始。所以a[2]在這裡指的不是3,而是2。

如果我想單獨訪問向量的任何幾個元素呢?只要你知道它們的確切位置,在[]裡面你就可以用c()函式完成你想要的了,其實c()函式也生成了一個向量,所以下面的方法和上圖無異。同理得4 3 2的來頭。

簡練的程式碼總帶給人以好感。


2、矩陣

矩陣這個概念,放在C裡面可以叫做二維陣列,在這裡你可以理解為多個向量的組合(這和線性代數裡面的向量組基本一致)。但在矩陣生成的過程我並不認為是簡單的拼湊維度一樣的向量,因為它看上去更像向量生成,只不過你會規定一行(列)只能寫多少字,而當程式一行寫不下時它會換一行(列)繼續。


但當你訪問某一個元素的時候,你又確實是按下標來的,正如你在C裡面一樣。不過R的優勢在於,你可以直接訪問一行一列組成的向量。


如果你熟悉MATLAB或者Python的話,那對[2,]和[,4]的格式應該和你的鞋子一樣熟悉。這樣的預設只指明瞭行列,便能以一種在編譯原理作業中可能被認為是語法錯誤的姿態,方便的讓C裡面的幾十行程式碼華麗變為5個字母。那你有想過把行列都缺省了會怎樣麼?


結果當然也是華麗麗的,和直接輸入m沒有區別,輸出了矩陣的所有元素。

你可能會發現,上面生成m的語句,出來的結果是按列順序排列矩陣元素的。其實這也是矩陣生成的預設順序,但不是唯一的,你仍然能按行順序,不過下面的生成函式你值得擁有:


在做資料分析的時候可能還需要對每行每列進行解釋,這時候自然少不了標籤。


這看上去像是個日曆,當然我也是出於這個才舉出的這個例子。

3、陣列


當然陣列的訪問和矩陣是類似的,不過是多了一組下標。


4、資料框

如果你剛從C/C++或者java陣營偷偷跑過來了解R,那接下來的資料型別可能讓你眼前一亮,它更像是資料庫裡面的操作,甚至很好的契合的你在資料處理上的一些需求。在向量、矩陣和陣列中,我們只能放入同一種資料型別,所以那些箱子或者包裹裡面你甚至不能同時將5.56mm子彈和7.62mm子彈放在一起,當然你也不允許向放了子彈的箱子裝手雷,如果你是個士兵的話我相信你會把這樣的箱子都突突了,特別是上級讓你保證後勤補給及時的時候。

好吧,比起矩陣,這才是真正的把向量拼湊在一起的資料型別。


如果你來自BAT的T,你對T2.1肯定比我瞭解。與矩陣那時不同,這裡的age可能不是標籤那麼簡單了。

因為你可以針對性的輸出某一列,你甚至能用$符號表示一個數據框的變數:


如果一個數據框有很多變數,而在某一段程式碼中又需要引用它的很多個變數,那麼使用$的話就需要在每次引用變數的時候都加上“資料框名$”的字首,就像你以前學C++而且不知道using namespace std;的時候,每次都可能寫很多std::。在R裡面我們其實也有using namespace std;這樣的簡化操作,不過形式有點不一樣:

time <- c(1 : 8)
temp <- c(1, 2, 4, 3, 5, 2, 4, 7)
tdata <- data.frame(time, temp)
attach(tdata)
plot(time, temp)
detach(tdata)

也許這個例子不夠好,但如果有兩個資料框,假設它們叫tdata1和tdata2,它們都有temp這個變數,但tdata1表示的是北京的溫度資料,而tdata2是南京的資料,那直接引用time和temp進行繪圖就會出現二義性的問題。而attach和detach比較方便的解決了部分問題,在attach和detach之間的變數引用,可以省去$部分。


5、因子

這似乎是個很抽象的概念。

其實之前你已經用到過因子的概念,還記得資料框那裡的例子麼,我們來看看字元型資料變數status在資料框裡面是什麼樣:


顯然,factor的意思就是因子。在用文字資料建立資料框的時候,R會將文字預設為類別資料並轉換。levels顯示的是該變數的因子水平,這在R裡面是一個術語,如果你能把因子當成列舉型別去思考,那因子水平看上去就像是一個列舉類的定義,當然在這裡它是動態的。


6、列表

列表可以算作R語言的基本型別中最複雜的了,列表的定義稱之為:一些成分的有序集合,而成分可以是任何資料型別,甚至可以是列表。


幾乎就像結構體一般,引用起來也很方便。


我現在差不多已經明白為什麼有人說,

有的語言,一行程式碼,

就能解決另一些語言成百上千行程式碼才能實現的功能。

當然這基本是拋開時間成本對比而言的。