我想知道字符串中是否有任何元素出现在其他字符串中。
我的数据包含数百万行,其结构为以下模拟数据:
dt <- data.table(product = c("A", "B", "C", "A,C,E", "A,B", "A,B,C", "D", "A", "B", "A", "A", "A,B,C", "D", "D"),
stock = c("A", "A,B", "A,B,C", "A,B,C,E", "A,B,C,E", "A,B,C,E", "A,B,C,D,E", "A", "A,B", "A,B", "A", "A,B,C", "A,B,C,D", "A,B,C,D"), stringsAsFactors = F)
dt[, product.2 := shift(product, type = "lead")]
dt[, product.3 := shift(product, n = 2, type = "lead")]
> dt
product stock product.2 product.3
1: A A B C
2: B A,B C A,C,E
3: C A,B,C A,C,E A,B
4: A,C,E A,B,C,E A,B A,B,C
5: A,B A,B,C,E A,B,C D
6: A,B,C A,B,C,E D A
7: D A,B,C,D,E A B
8: A A B A
9: B A,B A A
10: A A,B A A,B,C
11: A A A,B,C D
12: A,B,C A,B,C D D
13: D A,B,C,D D <NA>
14: D A,B,C,D <NA> <NA>
根据这些数据,我想了解以下内容:
comma
中的任何元素(用product.3
分隔)在product.2
中出现comma
中没有出现product.3
中的任何元素(用stock
分隔)。 comma
中的所有元素(由product.3
分隔)是否都在stock
中出现?预期结果是这样的:
> dt
product stock product.2 product.3 outcome1 outcome2 outcome3
1: A A B C FALSE FALSE FALSE
2: B A,B C A,C,E TRUE TRUE FALSE
3: C A,B,C A,C,E A,B TRUE TRUE TRUE
4: A,C,E A,B,C,E A,B A,B,C TRUE TRUE TRUE
5: A,B A,B,C,E A,B,C D FALSE FALSE FALSE
6: A,B,C A,B,C,E D A FALSE TRUE TRUE
7: D A,B,C,D,E A B FALSE TRUE TRUE
8: A A B A FALSE TRUE TRUE
9: B A,B A A TRUE TRUE TRUE
10: A A,B A A,B,C TRUE TRUE FALSE
11: A A A,B,C D FALSE FALSE FALSE
12: A,B,C A,B,C D D TRUE FALSE FALSE
13: D A,B,C,D D <NA> FALSE FALSE FALSE
14: D A,B,C,D <NA> <NA> FALSE FALSE FALSE
该问题是有关Stackoverflow的this问题的一部分。
编辑08/20/2019 :包括第三项预期结果。
答案 0 :(得分:4)
library(data.table)
library(stringr)
根据?str_detect
通过字符串和模式进行矢量化。等效于grepl(pattern,x)。有关grep(pattern,x)的等效信息,请参见str_which()。
因此,一种选择是将,
替换为|
(或匹配项),然后将“ product.2”和“ product.3”的对应元素直接与“ stock”比较进行比较在“ product.3”上。然后,将NA
的{{1}}元素替换为FALSE
set
前两行代码可以简化为@ d.b所述
dt[, outcome1 := str_detect(product.2, str_replace_all(product.3, ",", "|"))]
dt[, outcome2 := str_detect(stock, str_replace_all(product.3, ",", "|"))]
for(j in names(dt)[5:6]) set(dt, i = which(is.na(dt[[j]])), j = j, value = FALSE)
dt
# product stock product.2 product.3 outcome1 outcome2
# 1: A A B C FALSE FALSE
# 2: B A,B C A,C,E TRUE TRUE
# 3: C A,B,C A,C,E A,B TRUE TRUE
# 4: A,C,E A,B,C,E A,B A,B,C TRUE TRUE
# 5: A,B A,B,C,E A,B,C D FALSE FALSE
# 6: A,B,C A,B,C,E D A FALSE TRUE
# 7: D A,B,C,D,E A B FALSE TRUE
# 8: A A B A FALSE TRUE
# 9: B A,B A A TRUE TRUE
#10: A A,B A A,B,C TRUE TRUE
#11: A A A,B,C D FALSE FALSE
#12: A,B,C A,B,C D D TRUE FALSE
#13: D A,B,C,D D <NA> FALSE FALSE
#14: D A,B,C,D <NA> <NA> FALSE FALSE
随着OP问题的更新
dt[, paste0("outcome", 1:2) := lapply(.SD, str_detect,
pattern = str_replace_all(product.3, ",", "|")), .SDcols = c("product.2", "stock")]
答案 1 :(得分:3)
split
product.3
以逗号分隔,然后使用grepl
检查它是否出现在product.2
或stock
temp = strsplit(dt$product.3, ",")
sapply(seq_along(temp), function(i){
any(sapply(temp[[i]], function(x) grepl(x, dt$product.2[i])))
})
# [1] FALSE TRUE TRUE TRUE FALSE FALSE FALSE FALSE TRUE TRUE FALSE
#[12] TRUE NA NA
sapply(seq_along(temp), function(i){
any(sapply(temp[[i]], function(x) grepl(x, dt$stock[i])))
})
# [1] FALSE TRUE TRUE TRUE FALSE TRUE TRUE TRUE TRUE TRUE FALSE
#[12] FALSE NA NA