按R data.table中的条件拆分行

时间:2016-01-24 12:34:14

标签: r data.table

我有一个包含3列的数据表,其中一列 包含一个键:不同长度的值列表。 我希望重新排列表格,使每行只有一个键,以值

为条件

例如,假设我希望得到值为< = 2的所有行,以便每个键都在它自己的行上:\

input_tbl <-
data.table::data.table(a=c("AA"),b=c("{\"ha:llo\":1,\"wor:ld\":2,\"doog:bye\":3}"),
c=c(1))

所需的表格应该是

tbl_output <- data.table::data.table(a=c("AA",
"AA"),b=c("ha:llo","wor:ld"), c=c(1,1), s=c(1,2))

我尝试过以下功能:

data_table_clean <- function(dt){

  dt[ ,"b" := data.table::tstrsplit(b, ',', fixed = T),by=c(a, c)]
  dt[,c('b', 's'):= data.table::tstrsplit(b, ':', fixed=TRUE)]
    return(dt[s <=2,])

}

这会产生以下错误

  

&#34; eval中的错误(expr,envir,enclos):object&#39; a&#39;找不到&#34;

欢迎任何建议,当然。

密钥实际上是以下形式:

input2_tbl <-
data.table::data.table(a=c("AA"),b=c("{\"99:1d:3u:7y:89:67\":1,\"99:1D:34:YY:T6:Y6\":2,\"ll:5Y:UY:56:R5:R6\":3}"),
c=c(1))

因此输出表应为:

 tbl2_output <- data.table::data.table(a=c("AA",
 "AA"),b=c(""99:1d:3u:7y:89:67","99:1D:34:YY:T6:Y6"), 
    c=c(1,1), s=c(1,2))

谢谢!

更新

data_table_clean <- function(dt){



  res <- dt[, data.table::tstrsplit(unlist(strsplit(gsub('[{}"]', '', b),',', fixed=TRUE)), ":(?=[^:]+$)", perl=TRUE),
                     by = .(a, c)][V2 > -100]

  data.table::setnames(res, 3:4, c("b", "s"))
  res
}

运行时我收到以下错误:

  

.subset(x,j)中的错误:无效的下标类型&#39; list&#39;

2 个答案:

答案 0 :(得分:2)

一种选择是在最终输出中提取我们需要的字符。我们使用str_extract在“a”,“c”分组后执行此操作。输出为list,我们unlist将非数字和数字转换为两列,然后使用条件s<3对行进行子集。

library(stringr)
library(data.table)
input_tbl[, {
     tmp <- unlist(str_extract_all(b, "[A-Za-z]+:[A-Za-z]+|\\d+"))
       list(b=tmp[c(TRUE, FALSE)], s=tmp[c(FALSE, TRUE)])
     }, by = .(a,c)][s<3]
#    a c      b s
#1: AA 1 ha:llo 1
#2: AA 1 wor:ld 2

如果我们使用strsplit/tstrsplit,按'a','c'分组,我们会删除带有[{}]"的大括号和引号(gsub),除以{{1 (,),strsplit输出,然后使用unlist拆分tstrsplit后跟一个数字。子集部分与上面类似。

:

更新

对于更新的数据集,我们可以在最后一个分隔符(res <- input_tbl[, tstrsplit(unlist(strsplit(gsub('[{}"]', '', b), ',', fixed=TRUE)), ":(?=\\d)", perl=TRUE) ,.(a,c)][V2<3] setnames(res, 3:4, c("b", "s")) res # a c b s #1: AA 1 ha:llo 1 #2: AA 1 wor:ld 2 )上执行tstrsplit

:

答案 1 :(得分:1)

由于您似乎正在使用JSON对象,为什么不使用解析JSON的东西,例如“jsonlite”包?

有了它,你可以创建一个简单的函数,如下所示:

myFun <- function(invec) {
  require(jsonlite)
  x <- fromJSON(invec)
  list(b = names(x), s = unlist(x))
}

现在,应用于您的数据集,您将获得:

input_tbl[, myFun(b), by = .(a, c)]
#     a c        b s
# 1: AA 1   ha:llo 1
# 2: AA 1   wor:ld 2
# 3: AA 1 doog:bye 3

并且,对于子集:

input_tbl[, myFun(b), by = .(a, c)][s <= 2]
#     a c      b s
# 1: AA 1 ha:llo 1
# 2: AA 1 wor:ld 2

你甚至可以重写myFun函数来添加一个“阈值”参数,让你在函数本身内进行子集化。