Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
避免strsplit列表上的循环_R - Fatal编程技术网

避免strsplit列表上的循环

避免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],";")[[

我有一个向量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)
}
不幸的是,我的向量有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