将字符串拆分并保留其中一个特定部分。

3

在我的data.table中,我使用tstrsplit函数来拆分ValueId列,并设置keep=参数。但是在这种情况下,我不知道要放什么值在keep参数里,并且我想使用Level列中的值。

我所有的尝试都失败了。这是否可能?也许在data.table中不行?

以下是一个示例:

library(data.table)

foo <- data.table(Level = c(2,2,3,4,3),
                  ValueId = c("11983:1055521", "11983:1055521-5168:290668-198:100798", "11983:1055521-5168:290668-198:100798-92:91604-139:94569-135:94719-5161:290771-5162:290728-5166:290620",
                             "11983:1055521-5168:290668-198:100798-92:91604-139:94569-135:94719-5161:290771", " 11983:1055521-5168:290676-198:100794-92:91781-139:95090-135:95353"))

foo[, newvar := tstrsplit(ValueId, "-", fixed = TRUE, keep = 4)]

foo[, newvar := tstrsplit(ValueId, "-", fixed = TRUE, keep = Level)]

谢谢!!

2个回答

2
你可以使用 mapply[ 来提取由 strsplit 返回的子字符串,位置由 foo$Level 给出。
mapply(`[`, strsplit(foo$ValueId, "-", fixed = TRUE), foo$Level)
#[1] NA            "5168:290668" "198:100798"  "92:91604"    "198:100794" 

1

有几个问题。其中一个在tstrsplit函数本身中定义为:

function (x, ..., fill = NA, type.convert = FALSE, keep, names = FALSE) 
{
  if (!isTRUEorFALSE(names) && !is.character(names)) 
    stop("'names' must be TRUE/FALSE or a character vector.")
  ans = transpose(strsplit(as.character(x), ...), fill = fill, 
                  ignore.empty = FALSE)
  if (!missing(keep)) {
    keep = suppressWarnings(as.integer(keep))
    chk = min(keep) >= min(1L, length(ans)) & max(keep) <= 
      length(ans)
    if (!isTRUE(chk)) 
      stop("'keep' should contain integer values between ", 
           min(1L, length(ans)), " and ", length(ans), 
           ".")
    ans = ans[keep]
  }
  if (type.convert) 
    ans = lapply(ans, type.convert, as.is = TRUE)
  if (isFALSE(names)) 
    return(ans)
  else if (isTRUE(names)) 
    names = paste0("V", seq_along(ans))
  if (length(names) != length(ans)) {
    str = if (missing(keep)) 
      "ans"
    else "keep"
    stop("length(names) (= ", length(names), ") is not equal to length(", 
         str, ") (= ", length(ans), ").")
  }
  setattr(ans, "names", names)
  ans
}
<bytecode: 0x0000019bffd6da98>
  <environment: namespace:data.table>

重要的事情是注意 if 块,它检查您的 keep 是否适合返回。在您的示例中,第一行返回 NA。之所以在硬编码示例中有效是因为 strsplit 是向量化的,因此 NA 行与工作行同时运行,因此不会触发此 if 块。您可以通过将 4 更改为 40 来尝试此操作,然后您将获得此消息 Error in tstrsplit(ValueId, "-", fixed = TRUE, keep = 40) : 'keep' should contain integer values between 1 and 9. ,因为在这种情况下没有任何效果。
因此,您需要重新定义 tstrsplit 函数,以便它返回 NA 而不是停止。
tstrsplitNA<-function (x, ..., fill = NA, type.convert = FALSE, keep) 
{
  ans = transpose(strsplit(as.character(x), ...), fill = fill, 
                  ignore.empty = FALSE)
  if (!missing(keep)) {
    keep = suppressWarnings(as.integer(keep))
    chk = min(keep) >= min(1L, length(ans)) & max(keep) <= 
      length(ans)
    if (!isTRUE(chk)) 
      ans<-NA_character_
    ans = ans[keep]
  }
  if (type.convert) 
    ans = lapply(ans, type.convert, as.is = TRUE)
    return(ans)
  ans
}

这还不够,因为strsplit是向量化的,所以执行foo[, newvar := tstrsplitNA(ValueId, split="-", fixed = TRUE, keep = Level)]不仅仅是逐行运行该函数,而是将整个ValueId列提供给strsplit,然后对其进行转置,返回与您想要的内容不符的无意义结果。

您可以通过使用LevelValueId作为by参数,告诉data.table逐行执行操作。

foo[, newvar := tstrsplitNA(ValueId, split="-", fixed = TRUE, keep = Level), by=c('Level','ValueId')]

foo
  Level                                                                                               ValueId      newvar
1:     2                                                                                         11983:1055521          NA
2:     2                                                                  11983:1055521-5168:290668-198:100798 5168:290668
3:     3 11983:1055521-5168:290668-198:100798-92:91604-139:94569-135:94719-5161:290771-5162:290728-5166:290620  198:100798
4:     4                         11983:1055521-5168:290668-198:100798-92:91604-139:94569-135:94719-5161:290771    92:91604
5:     3                                     11983:1055521-5168:290676-198:100794-92:91781-139:95090-135:95353  198:100794

哇!让我预留一天时间,从你的答案中学习!! - Discus23
1
要使其工作,您只需要使用tstrsplitNA函数并使用“by”参数。 - Dean MacGregor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接