[心得] 資料整理套件介紹-第三章 dplyr(下)
這章將要繼續上章未完的dplyr
以下是這章主要內容:
A. 取唯一列:distinct, data.table:::unique
B. 列行運算:rowwise, plyr:::colwise
C. 值映射(對應修改):plyr:::mapvalues, plyr:::revalue
D. 其他函數:summarise_each, mutate_each
E. 特殊函數:plyr:::here
F. function with underscore suffix
1. 取唯一列
我在第一章 data.table提過 unique
distinct是一樣的方法
就從data.table:::unique的例子開始
` R
DT = data.table(A = rbinom(5, 1, 0.5), B = rbinom(5, 1, 0.5))
# A B
# 1: 0 0
# 2: 0 1
# 3: 1 0
# 4: 0 1
# 5: 0 0
unique(DT)
# A B
# 1: 0 0
# 2: 0 1
# 3: 1 0
distinct(DT)
# A B
# 1: 0 0
# 2: 0 1
# 3: 1 0
unique(DT, by = "A")
# A B
# 1: 0 0
# 2: 1 0
distinct(DT, A)
# A B
# 1: 0 0
# 2: 1 0
`
但是如mutate, filter等函數
distinct也可以給由變數組成的其他條件來做取唯一列的動作
給個簡單例子:
` R
distinct(DT, A*B)
# A B A * B
# 1: 0 0 0
`
2. 列行運算
mutate提供了列運算的函數 rowwise
雖然沒有apply好寫,不過效率確實好上不少
至少在chain上可以比較輕易地套用了
要介紹rowwise,還需要介紹do這個函數
do提供一些廣泛的運算方式
像是你可以根據不同變數設立模型如範例所示
` R
set.seed(100)
DF = data.frame(A = sample(1:5, 50, TRUE),
y = rnorm(50), x = rnorm(50))
models = DF %>% group_by(A) %>% do(model = lm(y ~ x, data = .))
models %>% summarise(mse = mean(model$residuals**2))
# mse
# 1 0.07560431
# 2 0.03617592
# 3 0.71000090
# 4 0.35385491
# 5 1.39799410
DT = data.table(A = sample(1:5, 50, TRUE),
y = rnorm(50), x = rnorm(50))
models = group_by(DT, A) %>% do(model = lm(y ~ x, data = .))
models %>% rowwise %>% summarise(mse = mean(model$residuals**2))
# mse
# 1 0.8953635
# 2 0.3954457
# 3 0.1469698
# 4 0.6303710
# 5 0.2966472
`
data.table出來的結果不會自動group_by row
要自己手動加入rowwise,這點需要注意
do應該有更多應用,需要各位好好開發。
再來,給一個rowwise的應用:
` R
set.seed(100)
(DT = data.table(A = rnorm(5), B = rnorm(5), C = rnorm(5)))
# A B C
# 1: -0.50219235 0.3186301 0.08988614
# 2: 0.13153117 -0.5817907 0.09627446
# 3: -0.07891709 0.7145327 -0.20163395
# 4: 0.88678481 -0.8252594 0.73984050
# 5: 0.11697127 -0.3598621 0.12337950
DT %>% rowwise %>%
do(k = c(.$A, .$B, .$C)[between(c(.$A, .$B, .$C), 0, 1)]) %>%
summarise(size = length(k), sums = sum(k))
# size sums
# 1 2 0.4085162
# 2 2 0.2278056
# 3 1 0.7145327
# 4 2 1.6266253
# 5 2 0.2403508
`
colwise提供每一行的做一個動作的方法
其實等同於你用sapply做
只是它還可以讓你選擇你要做的column去做
簡單例子如下:
` R
set.seed(100)
(DT = data.table(A = rnorm(5), B = rnorm(5), C = rnorm(5)))
# A B C
# 1: -0.50219235 0.3186301 0.08988614
# 2: 0.13153117 -0.5817907 0.09627446
# 3: -0.07891709 0.7145327 -0.20163395
# 4: 0.88678481 -0.8252594 0.73984050
# 5: 0.11697127 -0.3598621 0.12337950
colwise(function(x) c(mean(x), sd(x)))(DT)
# A B C
# 1 0.1600685 0.1890685 -0.6537084
# 2 0.8140039 0.7824803 0.5610936
colwise(function(x) c(mean(x), sd(x)), .cols = .(A, B))(DT)
# A B
# 1 0.1600685 0.1890685
# 2 0.8140039 0.7824803
f = function(x) quantile(x, c(0.05, 0.95))
colwise(f)(DT)
# A B C
# 1 -0.4175373 -0.7765657 -0.1433299
# 2 0.7357341 0.6353522 0.6165483
`
3. 值映射(對應修改)
這一節要介紹兩個很好用的函數 plyr:::mapvalues, plyr:::revalue
這兩個函數再處理資料時一定很常用到
我們再整理資料時,有時候會遇到奇異值
我們要把它改成我們想要的值時
大部分人應該都會遇到這個問題
或是有時候我們需要組別整併時也會遇到
給一個簡單的example
` R
DT = data.table(col1 = sample(c("A", "B", "N"), 30, TRUE),
col2 = sample(c("A1", "B3", "C4", "U9", "Z5"), 30, TRUE),
col3 = sample(-2:2, 30, TRUE))
DT2 = copy(DT)
## example 1 - 當初keyin資料出問題,col1出現了"N"這個值,我們要通通改成NA
## 此處提供數種方法做
set(DT, which(DT$col1 == "N"), "col1", NA)
DT2 %>% mutate(col1 = ifelse(col1 == "N", NA, col1)) # transform同理
DT2 %>% mutate(col1 = revalue(col1, c(N = NA)))
DT2 %>% mutate(col1 = mapvalues(col1, "N", NA))
## example 2 - 我們想要把col2做調整 A1 改成 B3, U9改成Z5
## 這裡就直接提供用revalue以及mapvalues的方法
DT2 %>% mutate(col2 = revalue(col2, c(A1 = "B3", U9 = "Z5")))
DT2 %>% mutate(col2 = mapvalues(col2, c("A1", "U9"), c("B3", "Z5")))
## example 3 - 當初keyin時不小心搞錯col3的-2跟2的正負號,我們要把-2跟2做互換
DT2 %>% mutate(col3 = mapvalues(col3, c(-2, 2), c(2, -2)))
`
最後提示幾個重點,
revalue可以用在factor跟character上面,不能用在數值上
mapvalues可以用在integer, double跟character上面,factor要先轉chr
4. 其他函數
這兩個函數 summarise_each, mutate_each,我自己也很少用
我提供一些例子做操作,先用簡單的例子
` R
DT = data.table(X = rnorm(100), Y = rnorm(100))
DT %>% summarise_each(funs(c(median(.), mean(.))))
# X Y
# 1: -0.02923809 0.08238550
# 2: -0.09154615 0.05153845
DT = data.table(X = c(3,2), Y = c(1, 4))
DT %>% mutate_each(funs(half = . / 2))
# X Y
# 1: 1.5 0.5
# 2: 1.0 2.0
`
這例子只是很簡單的介紹他們的功能
可能需要時間來累積看看是否有什麼好方法去用這兩個函數
5. 特殊函數
介紹一個我覺得很有趣的函數 here
here可以幫助你再使用sapply系列時
可以使用mutate等
提一個簡單的例子
` R
DTs = resplicate(5, data.table(A = rnorm(5)), simplify = FALSE)
DTs = lapply(DTs, here(mutate), Asq = A**2)
`
6. function with underscore suffix
本章最後一個重點
怎麼使用像是filter_, select_, mutate_, ...這些以_結尾的function
這些以_結尾的function提供使用者使用string作為input
中間執行的過程透過 lazyeval 來執行
(其實dplyr大部分函數都透過這個套件)
來看幾個簡單的例子
` R
DT = data.table(A = rnorm(5), B = rnorm(5))
DT %>% select_("A")
DT %>% select(A)
DT %>% mutate(C = A*B)
(DT2 = DT %>% mutate_("A*B") %>% setnames("A*B", "C"))
`
這幾個例子應該可以很簡單的解釋有_的函數要怎麼使用
最後給個.dots的用法,這個代表說你可以製作適當的string放入
` R
DT = data.table(x = rnorm(100), y = rnorm(100))
(DT %<>% mutate_(.dots = c("x^2", "y^2")) %>%
setnames(c("x^2", "y^2"), c("xsq", "ysq")))
DT %>% select_(.dots = c("y", "xsq"))
`
再給一個簡單的例子
` R
DT = data.table(x1 = rnorm(100), x2 = rnorm(100))
cmds = paste0("x", 1:2, "^2")
newnames = c("xsq", "ysq")
DT %<>% mutate_(.dots = cmds) %>% setnames(cmds, newnames))
`
下一章應該會是最後一章了
主要內容是data.table中的 dcast跟melt
還有tidyr的 separate, spread, gather
[關鍵字]: dplyr
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 223.138.206.65
※ 文章網址: https://www.ptt.cc/bbs/R_Language/M.1437573669.A.FB6.html
推
09/19 18:35, , 1F
09/19 18:35, 1F
R_Language 近期熱門文章
PTT數位生活區 即時熱門文章