兩個字符的向量的我有兩個列表:差分以substring
a <- c("da", "ba", "cs", "dd", "ek")
b <- c("zyc", "ulk", "mae", "csh", "ddi", "dada")
我想刪除從表b的元件,其將具有一個子串匹配的任何一箇中,例如,所述值的
grepl("da","dada") # TRUE
你會如何有效地做到這一點?
兩個字符的向量的我有兩個列表:差分以substring
a <- c("da", "ba", "cs", "dd", "ek")
b <- c("zyc", "ulk", "mae", "csh", "ddi", "dada")
我想刪除從表b的元件,其將具有一個子串匹配的任何一箇中,例如,所述值的
grepl("da","dada") # TRUE
你會如何有效地做到這一點?
我們可以paste
的「a」元素以單一的字符串|
作爲分隔符,使用它作爲在grepl
pattern
,否定(!
)到子集「B」。
b[!grepl(paste(a, collapse="|"), b)]
你可以嘗試以下方法:
b[!(+(apply(sapply(a, function(x) grepl(x,b)),1,sum)) > 0)]
[1] "zyc" "ulk" "mae"
「剝離」從裏面這個前面的調用,結果如下:首先,獲得從grepl:
呼叫匹配的矩陣(與sapply
):
sapply(a, function(x) grepl(x,b))
# da ba cs dd ek
#[1,] FALSE FALSE FALSE FALSE FALSE
#[2,] FALSE FALSE FALSE FALSE FALSE
#[3,] FALSE FALSE FALSE FALSE FALSE
#[4,] FALSE FALSE TRUE FALSE FALSE
#[5,] FALSE FALSE FALSE TRUE FALSE
#[6,] TRUE FALSE FALSE FALSE FALSE
注意,列的a
並且這些元件中的行的b
的元素。
然後,apply
每行的功能總和(以R
,TRUE爲1和FALSE爲0:
apply(sapply(a, function(x) grepl(x,b)),1,sum)
#[1] 0 0 0 1 1 1
注意,在這裏,該行資金可能是> 1(如果有超過1場),因此必須將其強制轉換爲邏輯與之前的通話纏:
+() > 0
有了這個,我們可以匹配([
)b的指數,但是因爲我們希望相反,我們請使用t他運營商!
。
#full code:
step.one <- sapply(a, function(x) grepl(x,b))
step.two <- apply(step.one,1,sum)
step.three <- +(step.two > 0)
step.four <- !step.three
#finally:
b[step.four]
正如大衛表示的意見,這是一個更優雅的方式:
b[-which(sapply(a, grepl, b), arr.ind = TRUE)[, "row"]]
如果你想在這裏使用'sapply','b [-which(sapply(a,grepl,b),arr。ind = TRUE)[,「row」]]''可能會比結合'apply' –
或'b [rowSums(sapply(a,grepl,x = b))== 0]'或者因爲你知道輸出的長度,使用更快的'vapply':'b [rowSums(vapply(a,grepl,x = b,logical(length(b))))== 0]' – thelatemail
這幾乎是我在找的東西for - 但顯然比grepl-way akrun建議的更復雜 – oliver13
,並用簡單的for循環另一種解決方案:
sel <- rep(FALSE, length(b))
for (i in seq_along(a)) {
sel <- sel | grepl(a[i], b, fixed = TRUE)
}
b[!sel]
不一樣優雅一些作爲其他的解決方案(特別是akrun的解決方案),但是顯示出for循環並不總是像人們相信的那樣慢:R:
fun1 <- function(a, b) {
sel <- rep(FALSE, length(b))
for (i in seq_along(a)) {
sel <- sel | grepl(a[i], b, fixed = TRUE)
}
b[!sel]
}
fun2 <- function(a, b) {
b[!apply(sapply(a, function(x) grepl(x,b, fixed=TRUE)),1,sum)]
}
fun3 <- function(a, b) {
b[-which(sapply(a, grepl, b, fixed=TRUE), arr.ind = TRUE)[, "row"]]
}
fun4 <- function(a, b) {
b[!grepl(paste(a, collapse="|"), b)]
}
library(stringr)
fun5 <- function(a, b) {
b[!sapply(b, function(u) any(str_detect(u,a)))]
}
a <- c("da", "ba", "cs", "dd", "ek")
b <- c("zyc", "ulk", "mae", "csh", "ddi", "dada")
b <- rep(b, length.out = 1E3)
library(microbenchmark)
microbenchmark(fun1(a, b), fun2(a, b), fun3(a,b), fun4(a,b), fun5(a,b))
# Unit: microseconds
# expr min lq mean median uq max neval cld
# fun1(a, b) 389.630 399.128 408.6146 406.007 411.7690 540.969 100 a
# fun2(a, b) 5274.143 5445.038 6183.3945 5544.522 5762.1750 35830.143 100 c
# fun3(a, b) 2568.734 2629.494 2691.8360 2686.552 2729.0840 2956.618 100 b
# fun4(a, b) 482.585 511.917 530.0885 528.993 541.6685 779.679 100 a
# fun5(a, b) 53846.970 54293.798 56337.6531 54861.585 55184.3100 132921.883 100 d
是的,微秒基準是毫無意義的,你應該創建一個更大的數據集IMO –
我猜不是!grepl也可以使用invert參數。但是:如果包含正則表達式字符(如「。」)會怎麼樣? – oliver13
回答我自己的問題:我在a向量上使用了http://stackoverflow.com/a/14838321/1563867,但我不確定這是做到這一點的最佳方式。 – oliver13
@ oliver13我想你解決了這個問題。如果不是,請考慮提供一些示例和預期輸出。 – akrun