我妹妹正在念大四,主修社會學。她剛剛簽了下個學期一份不錯的分析員工作,對方告訴她工作中要用到 R 程式語言。她讓我在寒假時教教她,我欣然同意了。還有什麼比這更好的方式來消磨明尼蘇達的冬天呢?[注1]
問題是:在原定教她的那天,我們倆都有空的時間只有一個小時。哎呀!
不過我還是接受了這個挑戰,用一個小時向我的社會學家妹妹介紹R。下面就是我所做的事情。我沒有預先做功課,而且肯定犯了些錯誤,忽視了核心思想,糾纏於細枝末節。但妹妹給我的反饋是非常好(我確實對其他人的“一小時學會R”理念非常感興趣)
(1)下載R和RStudio
我對RStudio的印象不錯,對於初學者來說,它既方便又很有幫助,對專業人士也很有用。尤其對於初學者:滑鼠指向-點選式(point-and-click)的選項非常棒,工作區皮膚對於建立起對R環境的概念也非常有用。我甚至都不用再花精力向我妹妹介紹R預設的整合開發環境——我馬上就讓她下載了RStudio,不過你仍然需要下載普通版的R。下載之後,我意識到r-project.org網站真應該在設計上進行大修整,因為:(a)它不夠漂亮(b)如果你不知道什麼是“CRAN映象”,下載R將是一件容易把人搞糊塗的事。
(2)控制檯和指令碼
準備好之後,我們做的第一件事就是在控制檯中鍵入如下兩行程式碼:
1 2 3 |
> x = 7 > x + 9 [1] 16 |
這並非純粹的“Hello World”,但它闡明瞭一些概念,比如”賦值”、”變數”和”求值”[注2]。
接著,我讓妹妹在一個R指令碼檔案中儲存了上面那兩行程式碼(我認為,在初學者開始使用一門語言時就教會他們如何正確地把程式碼儲存在指令碼檔案中是非常重要的)。然後,我教她怎麼用Cmd-Enter組合鍵(譯者注:這是Mac OS的鍵位。在PC中,對應的組合鍵是Ctrl+Enter)在控制檯中執行程式碼。
在解釋這些內容的過程中,我意識到”控制檯”和”指令碼”這類術語比較晦澀,所以我儘可能給出它們的明確的定義。我也不得不小心地使用那些含義確切的詞而非”REPL”或”prompt”這類詞彙
(3)註釋
1 |
# 註釋特別重要,所以我們學習了它 |
(4)圖形
指令碼、註釋和控制檯可能有點兒枯燥,所以到了這一步,該是從圖形中尋找點兒樂趣的時候了!這是我們繪製的一張圖:
1 2 |
x = rnorm(1000, mean = 100, sd = 3) hist(x) |
教我妹妹理解這段程式碼涉及解釋什麼是函式(因為rnorm和hist都是函式)、什麼是函式的實參,以及為什麼你可以通過名字引用實參卻不一定非得這樣做。
我還教她怎麼儲存一個圖形——藉助圖形視窗中方便的“Export”按鈕,在RStudio中儲存圖形非常容易。
(5)獲得幫助
我認為,“獲取幫助”是這類快速入門過程中需要掌握的最重要的概念。顯然你不可能在一個小時之內學會一切,所以,你真正需要的是當你用到時可以查詢到相應資訊的工具。下面是我介紹的語法:
1 2 3 4 |
# 如果你知道函式名,但不知道怎麼使用 ?chisq.test # 如果你知道要做什麼,但不知道函式名 ??chisquare |
考慮到查函式文件對非程式設計師來說不太容易,這本來或許不是一個正確的策略。我考慮過強調google技巧的重要性(我在研究生院學到的最有用的東西),或者介紹StackOverFlow和R-help,但最後還是決定講解官方的文件系統。”在R中我該怎麼做X這件事”是初學者最常見的問題之一,我認為這個問題的答案可能應該是”使用函式Y( )”——所以重要的是能夠搞清楚如何使用函式Y( )。
在我看來,初學者最常見的另一個問題是”我遇到了出錯資訊Z,怎麼修正它?”。為解決這個問題,我演示一些常見的錯誤(物件未找到,意外的<X>常量,等等)並解釋了它們的含義。
(6)資料型別
檢視幫助文件讓我想起文件中經常會提及某個函式的實參必須是某個特定的型別,因此我們或許應該討論一下資料型別。我介紹了:
向量
1 2 3 4 5 6 7 8 9 10 |
# 字串向量 > y = c("apple", "apple", "banana", "kiwi", "bear", "strawberry", "strawberry") > length(y) [1] 7 # 數值向量 > numbers = rep(3, 99) > numbers [1] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 [39] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 [77] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 |
矩陣
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
> mymatrix = matrix(c(10, 15, 3, 29), nrow = 2, byrow = TRUE) > mymatrix [,1] [,2] [1,] 10 15 [2,] 3 29 > t(mymatrix) [,1] [,2] [1,] 10 3 [2,] 15 29 > solve(mymatrix) [,1] [,2] [1,] 0.1183673 -0.06122449 [2,] -0.0122449 0.04081633 > mymatrix %*% solve(mymatrix) [,1] [,2] [1,] 1 0 [2,] 0 1 > chisq.test(mymatrix) Pearson's Chi-squared test with Yates' continuity correction data: mymatrix X-squared = 5.8385, df = 1, p-value = 0.01568 |
資料框(dataframe)
1 2 3 4 5 |
# 設定工作目錄 setwd("~/Documents/R_intro") # 讀入一個資料集 wages = read.table("wages.csv", sep = ",", header = TRUE) |
就這樣,我們藉助例項討論了一些資料型別,並順帶著學習了其他一些重要的內容,像怎麼確定向量中元素的個數、什麼是工作目錄,以及怎樣讀入資料檔案。
(7)探索性資料分析
一旦你讀入了一個資料集,事情就開始變得有趣了。我們從中學習了一大堆東西,像怎麼做基本的表格、遇到缺失資料如何處理,以及怎麼擬合一個簡單的線性模型。這部分的內容相當有趣,以至於我妹妹開始主導學習過程了:不再是我說“我要教你如何做什麼”,而是她主動問“嗯,我們能畫一個散點圖嗎?”或“你覺得我們可以把最優擬合直線放到那個圖上嗎?”我真為此而感到高興——我希望這意味著她已全身心投入並樂在其中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
> names(wages) [1] "edlevel" "south" "sex" "workyr" "union" "wage" "age" [8] "race" "marital" > class(wages$marital) [1] "integer" > table(wages$union) not union member union member 438 96 > summary(wages$workyr) Min. 1st Qu. Median Mean 3rd Qu. Max. 0.00 8.00 15.00 17.82 26.00 55.00 > nrow(wages) [1] 534 > length(which(is.na(wages$sex))) [1] 0 > linmod = lm(workyr ~ age, data = wages) > summary(linmod) |
我們還進一步學習了圖形,像怎麼作出好的直方圖,以及怎麼在迴歸直線上疊加散點圖。
1 2 3 |
hist(wages$wage, xlab = "hourly wage", main = "wages in our dataset", col = "purple") plot(wages$age, wages$workyr, xlab = "age", ylab="years worked", main = "age vs. years worked") abline(lm(wages$workyr ~ wages$age), col="red", lwd = 2) |
好了,時間到。
我遺漏了些什麼?哪些事能做得更好?我事後想到的有:
- 用[]取子集. 這是個關鍵知識點。它可以應用於我所介紹的所有資料型別,而且極為有用。我真希望當時有時間讓我妹妹做一個,比如只包含女性的工資直方圖
- 程式設計相關的東西:迴圈、if語句、使用者自定義函式,等等。不過我覺得不教這些東西也沒問題——考慮到受眾,我是把R當作一個資料分析環境而非一種程式語言來教授。
- 儲存.rda檔案和/或工作區
- 安裝和載入包
- 其他資料類(比如列表)
- 其他(更好的?)幫助資源/提示/技巧
最後一點感想
總的來說,在一小時內介紹R讓我收穫了樂趣,而且我認為(希望?)我妹妹也是如此。臨別時我又給了她一些資料:這個,這個和這個,這些資料我都不是非常熟悉——但我知道,要想能夠用R分析實際資料,所需的時間遠大於在我這兒的一個小時。我相信我已經覆蓋了大部分基礎知識,我妹妹也覺得這對她非常有幫助。我很樂意聽各位來談談你是如何應對”一小時內向非程式設計師介紹R”這個挑戰的。
腳註
注1. 即便對明尼蘇達來說,天氣也真的太冷了。溫度已在華氏0度(譯者注:攝氏-17度)左右徘徊了一個月之久。星期一的最高溫度是華氏-12度(譯者注:攝氏-24度)
注2.你可能注意到了,我用“=”來賦值,而且把這個習慣傳給了我妹妹。我考慮過這個問題並堅持這一用法,“<-”要多敲鍵盤,我發現它唯一有用的地方只是當我在system.time函式呼叫內進行賦值。