我有一个向量v,其中每个条目都是由分号分隔的一个或多个字符串(或可能的字符(0)):
ABC
DEF;ABC;QWE
TRF
character(0)
ABC;GFD我需要找到包含"ABC“(1,2,5或逻辑向量T,T,F,F,T)的向量的索引。
我目前使用的循环如下:
toSelect=integer(0)
for(i in c(1:length(v))){
if(length(v[i])==0) next
words=strsplit(v[i],";")[[1]]
if(!is.na(match("ABC",words))) toSelect=c(toSelect,i)
}不幸的是,我的向量有45万个条目,所以这花费的时间太长了。我更喜欢通过如下操作来创建逻辑向量
toSelect=(!is.na(match("ABC",strsplit(v,";")))但是因为strsplit返回一个列表,所以我找不到一种方法将strsplit(v,";")正确地格式化为一个向量(unlist不能做,因为它会破坏索引)。有没有人有任何关于如何加速这段代码的想法?
谢谢!
发布于 2013-05-08 03:51:11
使用正则表达式:
v = list("ABC", "DEF;ABC;QWE", "TRF", character(0), "ABC;GFD")
grep("(^|;)ABC($|;)", v)
#[1] 1 2 5发布于 2013-05-08 05:17:05
棘手的部分是处理character(0),@BlueMagister通过用character(1)替换它来进行模糊处理(这允许使用向量,但不允许表示原始问题)。也许吧
v <- list("ABC", "DEF;ABC;QWE", "TRF", character(0), "ABC;GFD")
v[sapply(v, length) != 0] <- strsplit(unlist(v), ";", fixed=TRUE)来做字符串拆分。可以使用base R,但我建议您使用IRanges包
source("http://bioconductor.org/biocLite.R")
biocLite("IRanges")来安装,然后
library(IRanges)
w = CharacterList(v)这给出了一个类似列表的结构,其中所有元素都必须是字符向量。
> w
CharacterList of length 5
[[1]] ABC
[[2]] DEF ABC QWE
[[3]] TRF
[[4]] character(0)
[[5]] ABC GFD然后,人们可以做一些有趣的事情,比如问“元素成员是否等于ABC”
> w == "ABC"
LogicalList of length 5
[[1]] TRUE
[[2]] FALSE TRUE FALSE
[[3]] FALSE
[[4]] logical(0)
[[5]] TRUE FALSE或“是否有任何元素成员等于ABC”
> any(w == "ABC")
[1] TRUE TRUE FALSE FALSE TRUE这将具有很好的伸缩性。对于不支持“开箱即用”的操作,策略(计算成本较低)是先unlist,然后转换为等长向量,然后使用原始CharacterList作为骨架进行relist,例如在每个成员上使用reverse:
> relist(reverse(unlist(w)), w)
CharacterList of length 5
[[1]] CBA
[[2]] FED CBA EWQ
[[3]] FRT
[[4]] character(0)
[[5]] CBA DFG正如@eddi指出的那样,这比grep慢。其动机是(a)避免需要制定复杂的正则表达式,同时(b)为像这样的结构化数据获得其他操作的灵活性。
发布于 2013-05-08 03:54:27
在sapply和%in%中使用strsplit
v <- c("ABC","DEF;ABC;QWE","TRF",character(1),"ABC;GFD")
sapply(strsplit(v,";"),function(x) "ABC" %in% x)
#[1] TRUE TRUE FALSE FALSE TRUEhttps://stackoverflow.com/questions/16427290
复制相似问题