tidyr包:reshape2的替代者,功能更純粹
tidyr包的應用
tidyr主要提供了一個類似Excel中數據透視表(pivot table)的功能;
gather和spread函數將數據在長格式和寬格式之間相互轉化,應用在比如稀疏矩陣和稠密矩陣之間的轉化;
separate和union方法提供了數據分組拆分、合並的功能,應用在nominal數據的轉化上
R將整潔數據定義為:每個變量的數據存儲在自身的列中,每個觀測值的數據存儲在其自身的行中。整潔數據是進行數據再加工的基礎。
tidyr包主要涉及:
1)缺失值的簡單補齊
2)長形表變寬形表與寬形表變長形表
gather-把寬度較大的數據轉換成一個更長的形式,它類比於從reshape2包中融合函數的功能
spread-把長的數據轉換成一個更寬的形式,它類比於從reshape2包中鑄造函數的功能。
gather()相反的是spread(),前者將不同的列堆疊起來,后者將同一列分開
3)列分割與列合並
separate-將一列按分隔符分割為多列
unite-將多列按指定分隔符合並為一列
tidyr包:(gather(寬數據轉為長數據)、spread(長數據轉為寬數據)、unit(多列合並為一列)、separate(將一列分離為多列))
栗子:
1.載入包
# 使用datasets包中的mtcars數據集做演示
library(tidyr)
library(dplyr)
head(mtcars)
# 為方便處理,在數據集中增加一列car mtcars$car <- rownames(mtcars)
mtcars <- mtcars[, c(12, 1:11)] #將添加的一列從最后一列移到最前列
head(mtcars)
2.gather--寬數據轉為長數據
使用gather()函數實現寬表轉長表,語法如下:
gather(data, key, value, …, na.rm = FALSE, convert = FALSE)
data:需要被轉換的寬形表
key:將原數據框中的所有列賦給一個新變量key
value:將原數據框中的所有值賦給一個新變量value
…:可以指定哪些列聚到同一列中
na.rm:是否刪除缺失值
開始使用:
# 除了car列外,其余列聚合成兩列,分別命名為attribute和value
mtcarsNew <- mtcars %>% gather(attribute, value, -car)
head(mtcarsNew)
tail(mtcarsNew)
如你所見,除了car列外,其余列聚合成兩列(一列對應列名,一列對應值),分別命名為attribute和value。
dplyr()利用%>%(鏈式操作)來改進:
鏈式操作是啥意思呢?
%>%的功能是用於實現將一個函數的輸出傳遞給下一個函數的第一個參數。注意這里的,傳遞給下一個函數的第一個參數,然后就不用寫第一個參數了。
tidyr很好的一點是可以只gather若干列而其他列保持不變。如果你想gather在map和gear之間的所有列而保持carb和car列不變,可以像下面這樣做:
# gather在map和gear之間的所有列,而保持carb和car列不變
mtcarsNew <- mtcars %>% gather(attribute, value, mpg:gear)
head(mtcarsNew)
連續篩選
不連續篩選
mtcarsNew <- mtcars %>% gather(`gear`,`carb`,key = "attribute", value = "value", -car)
head(mtcarsNew)
unique(mtcarsNew$attribute)
3.spread--長數據轉為寬數據
有時,為了滿足建模或繪圖的要求,往往需要將長形表轉換為寬形表,或將寬形表變為長形表。如何實現這兩種數據表類型的轉換。使用spread()函數實現長表轉寬表,語法如下:
spread(data, key, value, fill = NA, convert = FALSE, drop = TRUE)
data:為需要轉換的長形表
key:需要將變量值拓展為字段的變量
value:需要分散的值
fill:對於缺失值,可將fill的值賦值給被轉型后的缺失值
使用:
mtcarsSpread <- mtcarsNew %>% spread(attribute, value)
head(mtcarsSpread)
注:各列的相互位置稍有調整.
4.unite--多列合並為一列
unite的調用格式如下:
unite(data, col, …, sep = “_”, remove = TRUE)
data:為數據框
col:被組合的新列名稱
…:指定哪些列需要被組合
sep:組合列之間的連接符,默認為下划線
remove:是否刪除被組合的列
其作用是將多列合並為一列,舉例如下:
# 先虛構一數據框
set.seed(1)
date <- as.Date('2016-11-01') + 0:14
hour <- sample(1:24, 15)
min <- sample(1:60, 15)
second <- sample(1:60, 15)
event <- sample(letters, 15)
data <- data.table(date, hour, min, second, event)
# 把date,hour,min和second列合並為新列datetime
# R中的日期時間格式為"Year-Month-Day-Hour:Min:Second"
dataNew <- data %>%unite(datehour, date, hour, sep = ' ') %>%unite(datetime, datehour, min, second, sep = ':')
dataNew
若不習慣使用鏈式方式,這樣寫也可:
dt<-unite(data,datehour, date, hour, sep = ' ');dt
dt2<-unite(dt,datetime,datehour, min, second, sep = ':');dt2
5.separate--將一列分離為多列
separate()函數可將一列拆分為多列,一般可用於日志數據或日期時間型數據的拆分,語法如下:
separate(data, col, into, sep = “[^[:alnum:]]+”, remove = TRUE,
convert = FALSE, extra = “warn”, fill = “warn”, …)
data:為數據框
col:需要被拆分的列
into:新建的列名,為字符串向量
sep:被拆分列的分隔符
remove:是否刪除被分割的列
舉例如下:
# 可以用separate函數將數據恢復到剛創建的時候
# 首先,將datetime分為date列和time列 然后,將time列分為hour,min,second列
data1 <- dataNew %>%separate(datetime, c('date', 'time'), sep = ' ') %>%separate(time, c('hour', 'min', 'second'), sep = ':')
data1
一、缺失值的簡單補齊
library(tidyr)
創建含有缺失值的數據框示例
x <- c(1,2,7,8,NA,10,22,NA,15)
y <-c('a',NA,'b',NA,'b','a','a','b','a')
df <- data.table(x = x, y = y)
df
> x <- c(1,2,7,8,NA,10,22,NA,15)
> y <-c('a',NA,'b',NA,'b','a','a','b','a')
> df <- data.table(x = x, y = y)
> df
x y
1: 1 a
2: 2 NA
3: 7 b
4: 8 NA
5: NA b
6: 10 a
7: 22 a
8: NA b
9: 15 a
下面用x的均值或中位數替換缺失值,用y的眾數替換缺失值。
計算x的均值和中位數
x_mean <- mean(df$x, na.rm = TRUE)
x_median <- median(df$x, na.rm = TRUE)
> x_mean <- mean(df$x, na.rm = TRUE);x_mean
[1] 9.285714
> x_median <- median(df$x, na.rm = TRUE);x_median
[1] 8
計算y的眾數
y_mode <- as.character(df$y[which.max(table(df$y))])
> y_mode <- as.character(df$y[which.max(table(df$y))]);y_mode
[1] "a"
替換數據框df中x和y的缺失值
df2 <- replace_na(data = df, replace = list(x = x_mean, y = y_mode))
df2
> df2 <- replace_na(data = df, replace = list(x = x_mean, y = y_mode));df2
x y
1: 1.000000 a
2: 2.000000 a
3: 7.000000 b
4: 8.000000 a
5: 9.285714 b
6: 10.000000 a
7: 22.000000 a
8: 9.285714 b
9: 15.000000 a
df3 <- replace_na(data = df, replace = list(x = x_median, y = y_mode))
df3
> df3 <- replace_na(data = df, replace = list(x = x_median, y = y_mode));df3
x y
1: 1 a
2: 2 a
3: 7 b
4: 8 a
5: 8 b
6: 10 a
7: 22 a
8: 8 b
9: 15 a
上面的缺失值補齊方法只是簡單的使用指定值(可以是均值、中位數、眾數等),如果還想了解多重插補方法實現缺失值的處理,
********************************************************
可以參考:<缺失值處理方法>
首先了解一下處理缺失值的一般步驟:
1)識別缺失值;
2)檢測導致缺失數據的原因;
3)刪除包含缺失值的觀測或用合理的值代替缺失值。
第一步對缺失值的識別是非常簡單的,可以使用is.na()、is.nan()、和is.infinite()函數來鑒別數據集中是否存在缺失;
第二步需要根據實際的場景業務去理解缺失的原因,如敏感數據導致用戶不填或網絡、機器故障導致數據斷層等;
第三步是處理缺失的重要步驟,一般可以通過推理法、行刪除法和多重插補法進行處理。
一、識別缺失值
上面提到可以使用is.na()、is.nan()、和is.infinite()來鑒別數據集中是否存在缺失,但該方法返回的是所有向量或數據框中每一個元素是否為缺失值,顯然數據量非常大的話該方法返回的結果就不太容易接受。個人覺得可以使用mice包中的md.pattern()函數來發現數據集中缺失值的模式。但該方法只能識別R中的NA和NaN為缺失值,而不能將-Inf和Inf視為缺失值,處理的辦法可以用NA替代這些值。
例子
#創建數據集
set.seed(1234)
x1 <- runif(n = 1000, min = 1, max = 15)
x2 <- 100*rnorm(n = 1000) + 10
x3 <- rt(n = 1000, df = 3)
x4 <- rf(n = 1000, df1 = 2, df2 = 3)
y <- 2*x1 - 0.3*x2 + 0.6*x3 - 1.2*x4 + rnorm(1000)
nonemiss.df <- data.table(y = y, x1 = x1, x2 = x2, x3 = x3, x4 = x4)
#隨機將y,x3和x4列的某些觀測設為缺失值
set.seed(1234)
miss.df <- data.frame(y = y, x1 = x1, x2 = x2, x3 = x3, x4 = x4)
miss.df[sample(1:nrow(miss.df), 40),1] <- NA
miss.df[sample(1:nrow(miss.df), 50),2] <- NA
miss.df[sample(1:nrow(miss.df), 60),5] <- NA
#用mice包中的md.pattern()函數探索缺失值的模式
library(mice)
md.pattern(miss.df)
圖中返回了數據集中缺失值的情況,0表示列中存在缺失值,1表示列中不存在缺失值。
第一行描述數據集中沒有缺失值的模式;
從第二行至倒數第二行反映了某些列中會存在缺失值;
第一列表示缺失值的觀測數量(排除第一個值,即858);
最后一列表示缺失值的變量個數;
最后一行給出每個變量缺失值的個數。
通過這張缺失值模式表能夠清楚的發現哪些變量存在缺失值,而這些變量又包含了多少數量的缺失。還可以通過可視化的方法來探索數據集中存在缺失值的情況,本人比較喜歡使用VIM包中的aggr()函數。
例子
library(VIM)
aggr(miss.df, prop = FALSE, numbers = TRUE)
圖中能非常直觀的反映哪些變量存在缺失值及缺失情況如何。
二、缺失數據處理方法
推理法
該方法根據變量間的數學或邏輯關系進行填補或恢復缺失值,如根據某幾個變量間的關系來推斷缺失值可能的值;根據姓名來推斷缺失的性別或根據購買的產品特征推斷用戶可能所屬的年齡段等。
行刪除法
數據集中含有一個或多個缺失值的任意一行都會被刪除,一般假定缺失數據是完全隨機產生的,且缺失的量僅僅是數據集中的一小部分,可以考慮使用該方法進行缺失值的處理。
多重插補法
該方法是一種基於重復模擬的處理缺失值的方法,它將從一個含缺失值的數據集中生成一組完整的數據集,這些缺失值都是通過蒙特卡洛方法進行替補。替補方法有很多,如貝葉斯線性回歸法、自助線性回歸法、Logist回歸法和線性判別分析法等。
關於多重插補法可以使用mice包中的mice()函數(有關該函數的詳細說明可以查看R的幫助文檔),該包實現多重插補法並將完整數據集應用到統計模型中的思路如下:
1)mice()函數從一個含缺失值的數據框開始,返回一個包含多個完整數據集對象(默認可以模擬參數5個完整的數據集);
2)with()函數可依次對每個完整數據集應用統計建模;
3)pool()函數將with()生成的單獨結果整合到一起。
例子
library(mice)
im <- mice(data = miss.df, m = 10, method = 'pmm')
fit <- with(data = im, expr = lm(y ~ x1 + x2 + x3 + x4))
pooled <- pool(object = fit)
summary(pooled)
圖中給出了線性模型在填補缺失值后的數據集的返回結果。
為了比較,同樣將缺失數據集應用到線性模型中:
lm.fit <- lm(y ~ x1 + x2 + x3 + x4, data = miss.df)
summary(lm.fit)
發現缺失數據集和多重插補數據集應用到線性回歸后的參數估計基本一致,這主要是因為缺失值是完全隨機產生的。如果缺失值不是隨機產生的,且缺失比重比較大的話,就不適合使用行刪除法,而強烈建議使用多重插補法。
還有一種比較傳統的方法是用均值或中位數來替換缺失值,如果缺失數據量比較大的話,該方法可能會低估標准差和曲解變量間的相關性,導致錯誤的統計檢驗和P值。