感謝Robert I.Kabacoff 著作本書,同時感謝高濤、肖楠、陳鋼編譯此書。
最近在學習《R語言實戰》,特將學習過程記錄下來,供各位朋友參考,雖說是筆記,但是90%是書中內容,另外10%是自己偶爾冒出的一點點想法的記錄和一些疑問,希望互相探討。末尾有本章的代碼清單下載地址,與各位交流,還是提倡按照書中內容把代碼一個個敲出來。
第四章 基本數據管理
本章內容
操縱日期和缺失值
熟悉數據類型的轉換
變量的創建和重編碼
數據集的排序,合併與取子集
選入和丟棄變量
4.1 一個示例
代碼清單中,最後一行的最後一個參數,stringsAsFactors = FALSE,個人認爲含義是:特徵向量能否轉換爲因子,默認TRUE,可以轉換。R中解釋爲:
stringsAsFactors
logical: should character vectors be converted to factors? The ‘factory-fresh’ default is TRUE, but this can be changed by setting options(stringsAsFactors = FALSE)
4.2 創建新變量
在R中,算數運算符除了+、-、*、/,還有
^(或 **):求冪。
x%%y:求餘,5%%2的結果爲1。
x%/%y:整數除法,5%/%2的結果爲2。
代碼清單4-2提供了三種將新變量整合到原始的數據框中的方式。相當於在列表中增加新的一列(新的觀測)。作者推薦使用第三種方式,我個人也比較喜歡第三種,主要是簡便並且不容易誤操作。
4.3 變量的重編碼
重編碼涉及根據一個變量和/或其他變量的現有值創建新值得過程。
運算符 | 描述 |
4.4變量的重命名
- 交互式方法。
使用fix(數據框名)即可調出一個交互式的編輯器,可直接點擊變量名進行修改。 編程的方法
下載、載入reshape包,注意使用R 3.3.1版本。然後使用其中的rename()函數即可。編程的方式也分爲幾種方法:
直接將舊名稱換爲新名稱。
data.frame <- rename(oldname = "newname", oldname = "newname", …)
指定變換的變量數字。
names(data.frame)[2] <- "newname"
以向量的方式批量更換某一部分變量名。
names(data.frame)[2:5] <- c("newname", "newname", …)
4.5 缺失值
is.na()將返回邏輯值TRUE(存在缺失值)和FALSE(不存在缺失值)。
注意:
缺失值被認爲是不可比較的,即便是與確實值自身的比較。這一位這無法使用比較運算符來檢測缺失值是否存在。例如,邏輯測試myvar == NA的結果永遠不會是TRUE。作爲替代,你只能使用處理缺失值的函數(如本節中所述的那些)來識別R數據對象終歸的缺失值。
4.5.1 重編碼某些值爲缺失值
如4.3節那樣可以使用賦值語句將某些值重編碼爲缺失值。
leadership$age[leadership$age == 99] <- NA
請確保所有的缺失數據已在分析之前被妥善地編碼爲缺失值,否則分析結果將失去意義。
4.5.2 在分析中排出缺失值
缺失值需要以某種方式刪除,因爲含有缺失值的算術表達式和函數的計算結果也是缺失值。
多數數值函數擁有一個na.rm = TRUE的選項,可以在計算之前移除缺失值並使用剩餘值進行計算。
x <- c(1, 2, NA, 3)
y <- sum(x, na.rm = TRUE)
在使用函數處理不完整的數據時,請務必查閱他們的幫助文檔,檢查這些函數是如何處理缺失數據的。
函數na.omit()可以移除所有含有缺失值的觀測。
4.6 日期值
日期通常以字符串的方式輸入到R中,然後轉化爲以數值形式存儲的日期變量。函數as.Date()用於執行這種轉化。其語法爲:as.Date(x, “input_format“)
符號 | 含義 | 示例 |
%d | 數字表示的日期(0-31) | 01~31 |
%a | 縮寫的星期名 | Mon |
%A | 非縮寫的星期名 | Monday |
%m | 月份(00-12) | 00~12 |
%b | 縮寫的月份 | Jan |
%B | 非縮寫的月份 | January |
%y | 兩位數的年份 | 7 |
%Y | 四位數的年份 | 2007 |
在P73頁中有一句話,個人覺得,翻譯有誤。原文爲:
< 使用指定格式讀取字符型變量,並將其作爲一個日期變量替換到數據框中。
個人建議將第二句話改爲:並將其修改成指定格式的數值型變量(指定的日期格式)。
時間戳
- Sys.Date()函數 返回當天的日期。
date()函數 返回當前的日期和時間。
使用函數format(x, format = “output_format”)來輸出指定格式的日期值,並且可以提取日期值中的某些部分。
疑問
在使用如下代碼時,書中顯示的是英文的非縮寫月份,而在RStudio中是中文的月份。
today <- Sys.Date()
format(today, format = "%B %d %Y")
書中顯示的是:”December 01 2010”
而我操作時顯示的是:”六月 29 2016”
format(today, "%A")
書中顯示的是:”Wednesday”
而我操作時顯示的是:”星期三”
difftime()函數用於計算時間間隔,並以星期、天、時、分、秒來表示。units = auto(自動)、secs(秒)、mins(分)、hours(時)、days(天)、weeks(星期)。
問:爲何沒有年爲結果的參數選項?
4.6.1 將日期轉換爲字符型變量
strDate <- as.character(dates)
4.6.2 更進一步
要了解字符型數據轉換爲日期的更多細節,請查看help(as.Date)和help(strftime)。
要了解更多關於日期和時間格式的知識,請參考help(ISOdatetime)
lubridate包中包含了許多簡化日期處理的函數,可以用於識別和解析日期-時間數據,抽取日期-時間成分(例如年份、月份、日期等),以及對日期-時間值進行算術運算。
如果你需要對日期進行復雜的計算,namefCalendar包可能會有幫助。它提供了大量的日期處理函數,可以同時處理多個時區,並且提供了曆法操作功能,支持工作日、週末以及假期。
4.7 類型轉換
判斷 | 轉換 | 類型 |
is.numeric() | as.numeric() | 數值型 |
is.character() | as.character() | 字符型 |
is.vector() | as.vector() | 向量 |
is.martix() | as.martix() | 矩陣 |
is.data.frame() | as.data.frame() | 數據框 |
is.factor() | as.factor() | 因子 |
is.logical() | as.logical() | 邏輯型 |
名爲is.datatype()這樣的函數返回TRUE或FALSE,而as.datatype()這樣的函數則將其參數轉換爲對應的類型。
4.8 數據排序
使用order()函數對一個數據框進行排序。默認的排序順序是升序,在排序變量前邊加一個減號,即可得到降序的排序結果。order()可以同時添加多個變量。
4.9 數據集的合併
如果數據分散在多個地方,你就需要在繼續下一步之前將其合併。本節展示了向數據框中添加列(變量)和行(觀測)的方法。
4.9.1 添加列
使用merge()函數可以,通過一個或多個共有變量合併數據框。
如下代碼
ID <- c(1, 2, 3)
name1 <- c("a", "b", "c")
age1 <- c(11, 12, 13)
name2 <- c("d", "e", "f")
age2 <- c(14, 15, 16)
dataframe1 <- data.frame(ID, name1, age1)
dataframe1
dataframe2 <- data.frame(ID, name2, age2)
dataframe2
newdataframe <- merge(dataframe1, dataframe2, by = "ID")
newdataframe
以上是通過一個共有變量ID,合併兩個數據框的。
newdataframe2 <- cbind(dataframe1, dataframe2)
newdataframe2
使用cbind()函數可以直接橫向合併兩個矩陣或數據框。
4.9.2 添加行
使用rbind()函數可以縱向合併兩個數據框(數據集)。通常用於向數據框中添加觀測。
注意
- 兩個數據框必須擁有相同的變量,順序可以不同。
- 如果數據框A中有數據框B沒有的變量,請在合併之前做以下某種處理:
- 刪除A中的多餘變量。
- 在B中創建追加的變量並將其值設爲NA(缺失)。
4.10 數據集取子集
R擁有強大的索引特性,可以用於訪問對象中的元素。也可利用這些特性對變量或觀測進行選入和排除。
4.10.1 選入(保留)變量
myvars3 <- names(leadership) %in% c("q3", "q4")
newdata4 <- leadership[!myvars3]
newdata4
(1) names(leadership)生成了一個包含所有變量名的字符型向量:c(“manafer”, “date”, “country”, “gender”, “age”, “q1”, “q2”, “q3”, “q4”, “q5”)。
(2) names(leadership) %in% c(“q3”, “q4”)返回一個邏輯型向量,names(leadership)中每個匹配q3或q4的值爲TRUE,反之爲FALSE:c(FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE)。
(3)運算符非(!)將邏輯值翻反轉:c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE)。
(4) leadership[c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE)]選擇了邏輯值爲TRUE的列,於是q3和q4倍剔除了。
在知道q3和q4是第八個和第九個變量的情況下,可以使用語句:
newdata <- leadership[c(-8, -9)]
將他們剔除。原理是:**在某一列的下標之前加一個減號(-)就會剔除那一列了。
相同的變量刪除工作亦可通過:
leadership$q3 <- leadershi$q4 <- NULL
來完成。
將q3和q4設爲了未定義(NULL)。注意,NULL和NA是不同的。
4.10.3 選入觀測
選入或剔除觀測(行)通常是成功的數據準備和數據分析的一個關鍵方面。
代碼清單4-6 選入觀測
newdata <- leadership[1:3, ]
newdata
newdata <- leadership[which(leadership$gender == "M" & leadership$age > 30), ]
newdata
attach(leadership)
newdata <- leadership[which(gender == "M"& leadership$age > 30), ]
detach(leadership)
newdata
在以上的每個示例中,你只提供了行下標,並將列下標留空(故選入了所有列)。在第一個示例中,你選擇了第一行到第三行(前三個觀測)。
在第二個示例中,你選擇了所有30歲以上的男性。讓我們拆解這行代碼以便理解它。
(1) 邏輯比較leadership$gender == “M” 生成了向量c(TRUE, FALSE, FALSE, TRUE, FALSE)。
(2) 邏輯比較leadership$age > 30 生成了向量c(TRUE, TRUE, FALSE, TRUE, TRUE)。
(3) 邏輯比較c(TRUE, FALSE, FALSE, TRUE, FALSE) & c(TRUE, TRUE, FALSE, TRUE, TRUE)生成了向量c(TRUE, FALSE, FALSE, TRUE, FALSE)。
(4) 函數which()給出了向量中值爲TRUE元素的下標。因此,which(c(TRUE, FALSE, FALSE, TRUE, FALSE))生成了向量c(1, 4)。
(5) leadership[c(1, 4), ]從數據框中選擇了第一個和第四個觀測。這就滿足了我們選取準則(30歲以上的男性)。
第三個示例使用了attach()函數,所以就不必再變量名前加上數據框名稱了。
將研究範圍限定子啊2009年1月1日到2009年12月31日之間收集的觀測,使用以下代碼:
leadership$date <- as.Date(leadership$date, "%m/%d/%y")
startdate <- as.Date("2009-01-01")
enddate <- as.Date("2009-12-31")
newdate <- leadership[wihch(leadershi$date >= startdate & leadership$date <= enddate), ]
4.10.4 subset()函數
使用subset()函數可以簡便的選入觀測。
冒號運算符“:”,表示從…到…,在書中表示選擇保留的列。
4.10.5 隨機抽樣
sample()函數可以從數據集中(有放回或無放回地)抽取大小爲n的一個隨機樣本。
sample()函數中的第一個參數是一個由要從中抽樣的元素組成的向量,在這裏,這個向量是1到數據框中觀測的梳理,第二個參數是要抽取的元素數量,第三個參數表示無放回抽樣。sample()函數會返回隨機抽樣得到的元素,之後可用於選擇數據框中的行。
更進一步
R中擁有齊全的抽樣工具,包括抽取和小鄭調查樣本(詳見sampling包)以及分析複雜調查數據(詳見survey包)的工具其他依賴於抽樣的方法,包括自助法和重抽樣統計方法,詳見第11章。
4.11 使用SQL語句操作數據框
由於不會SQL以及沒有數據庫相關經驗,故跳過此章。