融化数据表和拆分值

时间:2017-01-11 17:03:08

标签: r data.table

我在数据表中有一个列,它是一个逗号分隔值列表

dt = data.table( a = c('a','b','c'), b = c('xx,yy,zz','mm,nn','qq,rr,ss,tt'))
> dt
   a           b
1: a    xx,yy,zz
2: b       mm,nn
3: c qq,rr,ss,tt

我想将其转换为长格式

   a  b
1: a xx
2: a yy
3: a zz
4: b mm
5: b nn
6: c qq
7: c rr
8: c ss
9: c tt

已针对数据框here回答了此问题。我想知道是否有一个优雅的数据表解决方案。

3 个答案:

答案 0 :(得分:1)

以下内容适用于您的示例:

dt[, c(b=strsplit(b, ",")), by=a]
   a b
1: a xx
2: a yy
3: a zz
4: b mm
5: b nn
6: c qq
7: c rr
8: c ss
9: c tt

如果在

中重复“by”变量,则此方法失败
dt = data.table(a = c('a','b','c', 'a'),
                b = c('xx,yy,zz','mm,nn','qq,rr,ss,tt', 'zz,gg,tt'))

在这种情况下,可以使用strsplit分割变量并构建新的data.tabe,从而获得一个强大的解决方案。 ID变量适当地循环使用填充缺失值的NA。然后使用is.na删除包含NA的行。

data.table(a=dt[,a], b=unlist(strsplit(dt[,b], ",")))[!is.na(b)]
    a  b
 1: a xx
 2: b mm
 3: c qq
 4: a zz
 5: a yy
 6: b nn
 7: c rr
 8: a gg
 9: a zz
10: c ss
11: a tt
12: c tt

答案 1 :(得分:1)

还有另一种方法,但是此方法涉及另一个包:splitstackshape。

library(splitstackshape)
cSplit(dt, "b", sep = ",", direction = "long")
   a  b
1: a xx
2: a yy
3: a zz
4: b mm
5: b nn
6: c qq
7: c rr
8: c ss
9: c tt

此功能使用data.table进行工作。即使我们对“ a”列具有多个相同的值,这项工作也可以实现。

答案 2 :(得分:-2)

我们可以split列'b'用分隔符','(使用strsplit),按'a'分组并设置新列的名称,即'V1'到'b 'with setnames

setnames(dt[, strsplit(b, ','), by = a], "V1", "b")[]
#   a  b
#1: a xx
#2: a yy
#3: a zz
#4: b mm
#5: b nn
#6: c qq
#7: c rr
#8: c ss
#9: c tt

如果'a'中有重复元素,如下例所示

dt <- data.table(a = c('a','b','c', 'a'),
            b = c('xx,yy,zz','mm,nn','qq,rr,ss,tt', 'zz,gg,tt'))

我们可以按行序列进行分组,对'b'进行strsplit,与'a'列连接,并将':=)'grp'分配给NULL

dt[, c(a=a, b=strsplit(b, ",")), .(grp = 1:nrow(dt))][, grp := NULL][]
#    a  b
# 1: a xx
# 2: a yy
# 3: a zz
# 4: b mm
# 5: b nn
# 6: c qq
# 7: c rr
# 8: c ss
# 9: c tt
#10: a zz
#11: a gg
#12: a tt

注意:这两种方法都是data.table方法