如何查找列表中是否包含子字符串?

时间:2019-07-28 22:03:41

标签: r string

我有一个新闻数据集(df),看起来或多或少像这样:

# v1     v2       subjects                                  body
# 1997   EMER   : ["N2:LEN", "N2:RTRS", "R:XON.N"],        "blablabla"
# 1998   EMER   : ["R:AAPL.N", "N2:MD", "N2:H"],           "blabla"
# 1998   AMEA   : ["N2:E", "N2:MD", "R:AA.T"],             "blabla2"

(不是很干净,因此主题列中的“:[”)。

然后我有一个主题列表(标签),实际上包含大约7万个元素:

# tags
# R:0#CRX*.A
# R:0#HMO*.A
# R:AA.N
# R:AAPL.N
# R:XON.N
# R:DELL.N

我只想保留df的行,其中df $ subjects包含标签中的至少一个元素(因此,在此示例中,我只想保留df的前两行)。我尝试了grepl:

tags_collapsed=paste(tags,collapse = "|")
tags_collapsed=gsub("[[:space:]]", "", tags_collapsed)

df=df[grepl(tags_collapsed,df$subjects),]

但是它给了我以下错误:

  

grepl(tags_collapsed,df $ subjects)中的错误:   无效的正则表达式   'R:0#CRX * .A | R:0#HMO * .A | R:AA.N | R:AAPL.N | ...

,不提供更多详细信息。我还尝试排除带有特殊字符的标签(例如,不带R:0#CRX * .A | R:0#HMO * .A),它会给出相同的错误。

相反,我尝试仅使用两个标签作为模式在df上应用grepl,并且有效。

任何建议将不胜感激!

数据。

df <-
structure(list(v1 = c(1997L, 1998L, 1998L), v2 = structure(c(2L, 
2L, 1L), .Label = c("   AMEA", "   EMER"), class = "factor"), 
subjects = structure(c(2L, 3L, 1L), .Label = c("   : [N2:E, N2:MD, R:AA.T]", 
"   : [N2:LEN, N2:RTRS, R:XON.N]", "   : [R:AAPL.N, N2:MD, N2:H]"),
class = "factor"), body = structure(3:1, .Label = c("             blabla2", 
    "           blabla", "        blablabla"), class = "factor")),
class = "data.frame", row.names = c(NA, -3L))

tags <- scan(what = character(), text = '
R:0#CRX*.A
R:0#HMO*.A
R:AA.N
R:AAPL.N
R:XON.N
R:DELL.N
')

1 个答案:

答案 0 :(得分:1)

长模式 vector 问题可以通过lapply循环来解决。很长的 string 问题似乎是一个XY problem,其中paste/collapse之后的70K模式被一个巨大的字符串替换,这反过来又导致grep出现故障。

下面的代码使用lapply搜索模式。然后,它仅将唯一的,已排序的索引保留在df$subject中。

i <- lapply(tags, grep, df$subjects)
i <- sort(unique(unlist(i)))
df[i, ]
#    v1      v2                        subjects              body
#1 1997    EMER    : [N2:LEN, N2:RTRS, R:XON.N]         blablabla
#2 1998    EMER       : [R:AAPL.N, N2:MD, N2:H]            blabla

现在使用70K模式向量进行测试。原始模式以字母扩展,足以匹配。因此,我包括tags并用sample随机播放。然后上面的代码重复。

set.seed(1234)
tags2 <- paste(tags, sample(letters, 70e3, TRUE), sep = ".")
tags2 <- sample(c(tags, tags2))
length(tags2)
#[1] 70006

j <- lapply(tags2, grep, df$subjects)
j <- sort(unique(unlist(j)))
df[j, ]
#    v1      v2                        subjects              body
#1 1997    EMER    : [N2:LEN, N2:RTRS, R:XON.N]         blablabla
#2 1998    EMER       : [R:AAPL.N, N2:MD, N2:H]            blabla