2

各エントリがセミコロンで区切られた 1 つ以上の文字列 (またはおそらく文字 (0)) であるベクトル v があります。

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 は実行できません)。このコードをスピードアップする方法について誰かアイデアがありますか?

ありがとう!

4

3 に答える 3

4

正規表現を使用します。

v = list("ABC", "DEF;ABC;QWE", "TRF", character(0), "ABC;GFD")
grep("(^|;)ABC($|;)", v)
#[1] 1 2 5
于 2013-05-07T19:51:10.993 に答える
3

トリッキーな部分は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)

文字列分割を行います。ベース 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、同じ長さのベクトルに変換しrelist、元の CharacterList をスケルトンとして使用することです。たとえば、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-07T21:17:04.570 に答える
2

strsplitsapplyを使用%in%:

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
于 2013-05-07T19:54:27.450 に答える