从R中的data.table中的列表创建虚拟变量

时间:2015-07-30 19:29:15

标签: r data.table dummy-variable

我有一个这样的数据表:

> x
   part        colig
 1:   PR     PT, PMDB
 2: PMDB     PT, PMDB
 3: PMDB     PT, PMDB
 4:  PDT     PT, PMDB
 5: PMDB     PT, PMDB
 6:  PFL PSDB,PFL,PTB
 7:  PPB PSDB,PFL,PTB
 8: PMDB PSDB,PFL,PTB
 9: PMDB PSDB,PFL,PTB
10:  PPB PSDB,PFL,PTB
> str(x)
Classes ‘data.table’ and 'data.frame':  10 obs. of  2 variables:
 $ part : chr  "PR" "PMDB" "PMDB" "PDT" ...
 $ colig:List of 10
  ..$ : chr "PT" "PMDB"
  ..$ : chr "PT" "PMDB"
  ..$ : chr "PT" "PMDB"
  ..$ : chr "PT" "PMDB"
  ..$ : chr "PT" "PMDB"
  ..$ : chr  "PSDB" "PFL" "PTB"
  ..$ : chr  "PSDB" "PFL" "PTB"
  ..$ : chr  "PSDB" "PFL" "PTB"
  ..$ : chr  "PSDB" "PFL" "PTB"
  ..$ : chr  "PSDB" "PFL" "PTB"
 - attr(*, ".internal.selfref")=<externalptr> 

我想创建一个虚拟变量,当第一个变量包含在第二个变量中时,该变量为1。我想要的输出是:

> x
    part        colig dummy
 1:   PR     PT, PMDB FALSE
 2: PMDB     PT, PMDB  TRUE
 3: PMDB     PT, PMDB  TRUE
 4:  PDT     PT, PMDB FALSE
 5: PMDB     PT, PMDB  TRUE
 6:  PFL PSDB,PFL,PTB  TRUE
 7:  PPB PSDB,PFL,PTB FALSE
 8: PMDB PSDB,PFL,PTB FALSE
 9: PMDB PSDB,PFL,PTB FALSE
10:  PPB PSDB,PFL,PTB FALSE

我的问题是访问第二列中列表中的元素。我尝试过这样的事情:

x[, dummy := x[,part] %in% x[, colig]]

x[, dummy := x[,part] %in% unlist(x[, colig])]

这两个选项都是错误的。在第一种情况下,dummy总是为FALSE,而在第二种情况下,unlist()命令创建一个列表,其中包含来自所有列表的元素(不仅来自相应的行)。

我也尝试过lapply(比如这里Creating dummy variables in R data.table):

x[, dummy := lapply( x[,part], function(y) y %in% unlist(x[,colig]))]

我认为是正确的,但我遇到速度问题,因为我有很多行。

有没有更快的选择?

3 个答案:

答案 0 :(得分:2)

使用grepl并按“part”的每个值执行:

x[, dummy := grepl(part, colig), by = part]

在第二次阅读OP时,我不确定该列中发生了什么 - 看起来有些元素是列表而其他元素是字符。以上内容适用于角色(您可以在某处挤压lapply(colig, toString)将列表转换为字符串)。

答案 1 :(得分:1)

尝试stringi,它应该很快。

library(stringi)
x$dummy = stri_detect(x[,"colig"], fixed=x[,"part"])
#    part        colig dummy
# 2    PR     PT, PMDB FALSE
# 3  PMDB     PT, PMDB  TRUE
# 4  PMDB     PT, PMDB  TRUE
# 5   PDT     PT, PMDB FALSE
# 6  PMDB     PT, PMDB  TRUE
# 7   PFL PSDB,PFL,PTB  TRUE
# 8   PPB PSDB,PFL,PTB FALSE
# 9  PMDB PSDB,PFL,PTB FALSE
# 10 PMDB PSDB,PFL,PTB FALSE
# 11  PPB PSDB,PFL,PTB FALSE

data.table

setDT(x)[, dummy := stri_detect(colig, fixed=part)]

修改

如果您看起来像列表和未分离字符串的混合,请尝试类似

的内容
setDT(x)[, dummy := any(stri_detect(colig, fixed=part)), by=1:nrow(x)]

答案 2 :(得分:0)

从您的str(x)输出中,您的数据似乎有些问题。 colig的前几行似乎没有拆分。换句话说,你可能意味着有两个元素&#34; PT&#34;,&#34; PMDB&#34;而不是单个元素&#34; PT,PMDB&#34;。这可能是问题的一部分。必要时应用strsplit

如果您的样本具有代表性,那么只需

apply(x,1,function(x) x$part %in% x$colig)

其中x只是data.frame应该足够快。我将x的更正版本复制到了100000行,这只是在几分之一秒内完成的。