如何将列添加到R中的data.table,该列基于另一列中的字符串?

Mir*_*iam 4 regex parsing r transform data.table

我想基于另一列中的字符串向data.table添加列.这是我的数据和我尝试过的方法:

                                                                                     Params
1:                                   { clientID : 459;  time : 1386868908703;  version : 6}
2: { clientID : 459;  id : 52a9ea8b534b2b0b5000575f;  time : 1386868824339;  user : 459001}
3:                                                 { clientID : 988;  time : 1388939739771}
4: { clientID : 459;  id : 52a9ec00b73cbf0b210057e9;  time : 1386868810519;  user : 459001}
5:                                                 { clientID : 459;  time : 1388090530634}

用于创建此表的代码:

DT = data.table(Params=c("{ clientID : 459;  time : 1386868908703;  version : 6}","{ clientID : 459;  id : 52a9ea8b534b2b0b5000575f;  time : 1386868824339;  user : 459001}","{ clientID : 988;  time : 1388939739771}","{ clientID : 459;  id : 52a9ec00b73cbf0b210057e9;  time : 1386868810519;  user : 459001}","{ clientID : 459;  time : 1388090530634}"))
Run Code Online (Sandbox Code Playgroud)

我想解析"Params"列中的文本,并根据其中的文本创建新列.例如,我希望有一个名为"user"的新列,它只保存Params字符串中"user:"之后的数字.添加的列应如下所示:

                                                                                     Params          user
1:                                   { clientID : 459;  time : 1386868908703;  version : 6} NA
2: { clientID : 459;  id : 52a9ea8b534b2b0b5000575f;  time : 1386868824339;  user : 459001} 459001
3:                                                 { clientID : 988;  time : 1388939739771} NA
4: { clientID : 459;  id : 52a9ec00b73cbf0b210057e9;  time : 1386868810519;  user : 459001} 459001
5:                                                 { clientID : 459;  time : 1388090530634} 459001

我创建了以下函数来解析(在本例中为"user"):

myparse <- function(searchterm, s) {
  s <-gsub("{","",s, fixed = TRUE)
  s <-gsub(" ","",s, fixed = TRUE)
  s <-gsub("}","",s, fixed = TRUE)
  s <-strsplit(s, '[;:]')
  s <-unlist(s)
  if (length(s[which(s==searchterm)])>0) {s[which(s==searchterm)+1]} else {NA}
}
Run Code Online (Sandbox Code Playgroud)

然后我使用以下函数添加一列:

DT <- transform(DT, user = myparse("user", Params))
Run Code Online (Sandbox Code Playgroud)

这适用于包含在所有行中的"时间"的情况,但在"用户"的情况下不起作用,"用户"仅包括在两行中.返回以下错误:

Error in data.table(list(Params = c("{ clientID : 459;  time : 1386868908703;  version : 6}",  : 
  argument 2 (nrow 2) cannot be recycled without remainder to match longest nrow (5)
Run Code Online (Sandbox Code Playgroud)

我该如何解决这个问题?谢谢!

Sve*_*ein 6

以下是使用正则表达式执行此任务的方法:

myparse <- function(searchterm, s) {
  res <- rep(NA_character_, length(s)) # NA vector
  idx <- grepl(searchterm, s) # index for strings including the search term
  pattern <- paste0(".*", searchterm, " : ([^;}]+)[;}].*") # regex pattern
  res[idx] <- sub(pattern, "\\1", s[idx]) # extract target string
  return(res)
}
Run Code Online (Sandbox Code Playgroud)

您可以使用此函数添加新列,例如user:

DT[, user := myparse("user", Params)]
Run Code Online (Sandbox Code Playgroud)

新列包含NA没有user字段的行:

DT[, user]
# [1] NA       "459001" NA       "459001" NA
Run Code Online (Sandbox Code Playgroud)