作者celestialgod (攸蓝)
看板R_Language
标题[心得] 资料整理套件介绍-终章 tidyr
时间Sat Jul 25 16:42:26 2015
本章是最後一章,主要介绍
1. data.table:::dcast.data.table
2. data.table:::melt
3. tidyr:::gather
4. tidyr:::spread
5. tidyr:::separate
这一章主要讲述注重在资料的呈现方式 - 横表跟直表的呈现
还有一些表格整合的问题
1. dcast.data.table
dcast提供直表加总的函数
学过统计的话,应该是contingency table (列联表)
或是熟悉EXCEL,知道枢纽分析表,它其实就是枢纽分析表
Y就是列联表中的列变数,X就是行变数
制作列联表也可以说它的应用之一
这个function,需要先`require(reshape2)`
有人可能会问reshape2就有dcast为啥要用dcast.data.table
原因很简单,因为dcast.data.table快更多!!
速度直接?dcast.data.table下面例子就有,直接来简介怎麽用
第一个input是data.table,第二个是给一个公式
举例来说,如果公式是 Y ~ X,Y的元素会展开在列,X就会在行
第三个input是加总函数,你如果有相同类别的X, Y
它会把相同类别的值用这个函数做加总,预设是length
先用一个简单例子来说明
` R
set.seed(100)
DT = expand.grid(LETTERS[1:2], LETTERS[3:4]) %>% data.table %>%
setnames(c("col1","col2")) %>% '['(rep(1:nrow(.), 2)) %>%
'['(,values := rpois(8,2))
DT
# col1 col2 values
# 1: A C 1
# 2: B C 1
# 3: A D 2
# 4: B D 0
# 5: A C 2
# 6: B C 2
# 7: A D 3
# 8: B D 1
dcast.data.table(DT, col1~col2)
# col1 C D
# 1: A 2 2
# 2: B 2 2
dcast.data.table(DT, col1~col2, sum)
# col1 C D
# 1: A 3 5
# 2: B 3 1
`
产生资料的函数、operator,我们都讲过了,往前找找看
我们专注到第一个dcast,dcast.data.table(DT, col1~col2)
可以看的出来 col1就在列,col2就在行展开,然後计算col1, col2有相同类别的length
第二个dcast就是把有相同的类别,把values做总和
但是,我们怎麽知道它加总的是values
它会告诉你自动找寻data.table,然後选定values做为加总的column
至於改法就是修改value.var这个input,举例来说
` R
DT[, values2 := rpois(8, 3)]
dcast.data.table(DT, col1~col2, sum, value.var = "values")
# col1 C D
# 1: A 3 5
# 2: B 3 1
dcast.data.table(DT, col1~col2, sum, value.var = "values2")
# col1 C D
# 1: A 5 7
# 2: B 3 9
DT[, col3 := rep(LETTERS[5:6],,,4)]
dcast.data.table(DT, col1+col2~col3, sum, value.var = "values")
# col1 col2 E F
# 1: A C 1 2
# 2: A D 2 3
# 3: B C 1 2
# 4: B D 0 1
`
dcast.data.table说明到此
2. melt
dcast做直表加总,melt做横表转直表
举个简单的例子
我们有数个病人,每个病人有数个观察值
表格纪录的样子是
id O1 O2
P1 12 18
P2 13 15
.. .. ..
我们想要转成直表长这样:
id O V
P1 O1 12
P1 O1 18
P2 O2 13
P2 O2 15
.. .. ..
那麽在R code可以这样做:
` R
(DT = data.table(id = paste0("P", 1:2), O1 = c(12,13), O2 = c(18,15)))
# id O1 O2
# 1: P1 12 18
# 2: P2 13 15
(DT_long = melt(DT, "id", variable.name = "O", value.name = "V"))
# id O V
# 1: P1 O1 12
# 2: P2 O1 13
# 3: P1 O2 18
# 4: P2 O2 15
`
melt的第一个input是data.table (注一)
第二个input是id.vars,也就是你要展开的变数名称
第三个input是measure.vars,你要展开的变数名称
前面例子未指定的情况下,就是全部的column
前面我还有用到variable.name 跟 value.name
variable.name是指定集合其他columns之後的column name
在前例就是把 O1, O2两个columns集合之後的变数名称,我改成了"O"
value.name是你集合其他columns之後那些变数值的column
在前例就是把 O1, O2两个columns集合之後的变数值,我改成了"V"
注一:此指data.table:::melt,跟reshape2:::melt的差异部分
请看data.table:::melt的help
我们再看一个复杂一点的例子
` R
DT = data.table(ID1 = paste0("ID1_", 1:20),
ID2 = sample(paste0("ID2_", 1:20)),
O1 = rnorm(20), O2 = rnorm(20), O3 = rnorm(20))
## 以ID1跟ID2作为展开,其他column (O1 ~ O3)会叠成一个变数
## 还会有一个新类别去label後面的value来自哪一个变数
melt(DT, c("ID1", "ID2"), c("O1", "O2", "O3"),
variable.name = "O", value.name = "V")
## 以ID1作为展开,其他column (O1 ~ O3)会叠成一个变数
## 还会有一个新类别去label後面的value来自哪一个变数
melt(DT, "ID1", c("O1", "O2", "O3"),
variable.name = "O", value.name = "V")
## 以ID1作为展开,其他column (O1 ~ O2)会叠成一个变数
## 还会有一个新类别去label後面的value来自哪一个变数
melt(DT, "ID1", c("O1", "O2"),
variable.name = "O", value.name = "V")
`
3. gather
其实就是melt,只是比较好写
我们把melt的例子改成用gather写
只是melt一次到位的指令用gather写之後
要用select跟filter做 (但是我觉得gather比较好写)
` R
(DT = data.table(id = paste0("P", 1:2), O1 = c(12,13), O2 = c(18,15)))
# id O1 O2
# 1: P1 12 18
# 2: P2 13 15
(DT_long = gather(DT, O, V, -id))
# id O V
# 1: P1 O1 12
# 2: P2 O1 13
# 3: P1 O2 18
# 4: P2 O2 15
DT = data.table(ID1 = paste0("ID1_", 1:20),
ID2 = sample(paste0("ID2_", 1:20)),
O1 = rnorm(20), O2 = rnorm(20), O3 = rnorm(20))
gather(DT, O, V, -ID1, -ID2)
gather(DT, O, V, -ID1, -ID2) %>% select(-ID2)
gather(DT, O, V, -ID1, -ID2) %>% select(-ID2) %>% filter(O!="O3")
`
4. spread
提供gather的反向操作
` R
DT = data.table(id = paste0("P", 1:2), O1 = c(12,13), O2 = c(18,15))
DT_long = gather(DT, O, V, -id)
DT_long %>% spread(O, V)
# id O1 O2
# 1: P1 12 18
# 2: P2 13 15
`
5. separate
把特定column做strsplit,并设定成新的变数
一个简单的例子
` R
DT = data.table(x = paste0(sample(LETTERS, 5), ",", sample(LETTERS, 5)))
DT %>% separate(x, paste0("V", 1:2))
`
这个函数要注意的是以下的程式是会出现错误的
` R
DT = data.table(x = paste0(sample(LETTERS, 5), sample(LETTERS, 5)))
DT %>% separate(x, paste0("V", 1:2))
`
separate无法分开没有间隔字元的字串
你要分开这个只能做适当的转换,像是:
` R
DT = data.table(x = paste0(sample(LETTERS, 5), sample(LETTERS, 5)))
DT %<>% mutate(x = gsub("([A-Z])", "\\1, ", x))
DT %>% separate(x, paste0("V", 1:3)) %>% select(-V3)
`
如果有人有更好的方法,麻烦告知我一下,谢谢
资料介绍套件就到这里结束
有任何问题,欢迎在板上回文询问,我有看到都会回覆
(麻烦尽量不要用私信,希望可以让板众一起看问题该怎麽解决)
有任何补充或是建议也欢迎推文或回文,感谢大家
我并没有讲到plyr的 a*ply, l*ply, d*ply, r*ply系列
其实他们跟apply, lapply, tapply, replicate相对应,只是output型式不同
如果未来有机会写有关*ply系列函数时,我再好好介绍plyr
[关键字]: tidyr
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 123.205.27.107
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/R_Language/M.1437813750.A.05B.html
※ 编辑: celestialgod (123.205.27.107), 07/25/2015 16:53:10
1F:推 andrew43: 快拜一下。 07/25 22:29
2F:推 psinqoo: 朝圣~ 07/26 08:51
3F:推 hyekyo0608: 跟着拜~ 07/27 09:49
4F:推 squallscer: 朝圣~ 07/27 20:14
5F:推 sacidoO: 有看有推 感谢C大分享宝贵经验! 06/14 13:39