避免strsplit列表上的循环
我有一个向量v,其中每个条目是一个或多个字符串(或者可能是字符(0)),用分号分隔:避免strsplit列表上的循环,r,R,我有一个向量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],";")[[
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)
}
不幸的是,我的向量有450k个条目,所以这需要太长时间。我更喜欢通过如下操作创建逻辑向量
toSelect=(!is.na(match("ABC",strsplit(v,";")))
但是由于strsplit返回一个列表,我找不到一种方法将strsplit(v,“;”)正确格式化为向量(unlist不行,因为它会破坏索引)。有人对如何加速这段代码有什么想法吗
谢谢 使用正则表达式:
v = list("ABC", "DEF;ABC;QWE", "TRF", character(0), "ABC;GFD")
grep("(^|;)ABC($|;)", v)
#[1] 1 2 5
在%中使用
strsplit
与sapply
和%
v <- c("ABC","DEF;ABC;QWE","TRF",character(1),"ABC;GFD")
sapply(strsplit(v,";"),function(x) "ABC" %in% x)
#[1] TRUE TRUE FALSE FALSE TRUE
v棘手的部分是处理字符(0)
,而@BlueMagister通过将其替换为字符(1)
(这允许使用向量,但不允许表示原始问题)。或许
安装,然后
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吗?”
或“任何元素成员是否等于ABC”
这将很好地扩展。对于不支持“开箱即用”的操作,策略(计算成本较低)是取消列出
,然后转换为等长向量,然后重新列出
,使用原始字符列表作为骨架,例如对每个成员使用反向
:
> 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)获得对这种结构的数据执行其他操作的灵活性。谢谢!但是list(v)只返回一个包含一个元素的列表,我无法手动键入所有条目@user2359686运行grep
不需要将向量转换为列表,而要转换为列表的函数是as.list
(我不知道如何将字符(0)
转换为向量)如果您想要逻辑向量而不是索引,那么使用grepl
而不是grep
。我认为@BlueMagister使用字符(1)
,因为他使用的是向量而不是列表。你应该试着把它放在凳子上——在我的基本测试中,这比在所有尺度上的grep'ing至少慢10倍,所以我很好奇为什么你认为人们会想经历这一切(痛苦?)。我假设字符(0)
是OP渲染“
,即字符(1)
,这是一个原子向量,根据其他条目的构成。我已经要求OP对v
的结构进行更多的澄清。这很好,但没有完全矢量化。作为另一种选择,考虑<代码> do.Calp(C,SrStReV(v);”)= =“ABC”< /代码>。请注意,这是一个次要的[3x]加速,但更多的是在'r'的向量化的精神中,作为一种选择,考虑<代码> unListar(SrStRead(v,);”)= =“ABC”< /代码>。在这里,unlist
[或更高版本,do.call(c,)
]将列表转换为一个向量。您能在问题中向我们展示dput(head(v))
?我们回答者不确定v
是字符的原子向量
还是列表
。
> w
CharacterList of length 5
[[1]] ABC
[[2]] DEF ABC QWE
[[3]] TRF
[[4]] character(0)
[[5]] ABC GFD
> w == "ABC"
LogicalList of length 5
[[1]] TRUE
[[2]] FALSE TRUE FALSE
[[3]] FALSE
[[4]] logical(0)
[[5]] TRUE FALSE
> any(w == "ABC")
[1] TRUE TRUE FALSE FALSE TRUE
> relist(reverse(unlist(w)), w)
CharacterList of length 5
[[1]] CBA
[[2]] FED CBA EWQ
[[3]] FRT
[[4]] character(0)
[[5]] CBA DFG