【问题标题】:Creating indicator variables based on pattern matches根据模式匹配创建指标变量
【发布时间】:2018-06-08 10:34:50
【问题描述】:

我有一个文本变量,我想创建指示变量来标识文本变量中的模式向量。 应该为每个模式创建一个新的指标变量(最好使用与模式相同的变量名称。

创建示例数据:

#rm(list = ls())
mydata <- read.table(
  header = T, con <- textConnection
  ('
ID text
6 "aaa"
7 "bbb"
10 "ccc"
11 "a bbb"
29 "a bbb"
30 "bbb"
31 "ddd"
'), stringsAsFactors = FALSE, fill = TRUE, strip.white = TRUE)
close(con)

单一模式匹配

# a single pattern
mydata$a <- as.integer(grepl(pattern = "aaa", x = mydata$text))
mydata$a

然后创建一个模式向量:

# multiple patterns stored in a vector
vecpat <- c("aaa", "bbb", "ccc", "ddd", "eee")

现在我的问题是如何调整上面的代码来为多个模式进行模式匹配和变量创建。 新变量显示添加到数据框中,标签为“aaa”、“bbb”、“ccc”、“ddd”、“eee”,值范围为 0 到 1。

我尝试使用 stringr 包中的 str_match_all 来执行此操作。但我不确定如何处理生成的对象。 以下链接 (https://rpubs.com/iPhuoc/stringr_manipulation) 对此进行了调查,但未提供比以下引用更多的信息: “如果你想提取第一个电话号码之外的内容,例如最后一个字符串中的第二个电话号码,你可以使用 str_match_all()。但是,就像 str_split() 它会为每个输入字符串返回一个包含一个组件的列表,并且你'将需要使用 lapply() 来处理结果。"

【问题讨论】:

  • 这是你需要的:sapply(vecpat, grepl, x=mydata$text)+0L

标签: r pattern-matching stringr


【解决方案1】:

你可以这样做......

for(i in vecpat){
  mydata[, i] <- as.integer(grepl(pattern = i, x = mydata$text))
}

mydata
  ID  text aaa bbb ccc ddd eee
1  6   aaa   1   0   0   0   0
2  7   bbb   0   1   0   0   0
3 10   ccc   0   0   1   0   0
4 11 a bbb   0   1   0   0   0
5 29 a bbb   0   1   0   0   0
6 30   bbb   0   1   0   0   0
7 31   ddd   0   0   0   1   0

对于没有任何显式循环的解决方案,您可以使用 outerstringr::str_detect(矢量化)...

library(stringr)
mydata[, vecpat] <- outer(mydata$text, vecpat, str_detect) + 0L

【讨论】:

  • 亲爱的安德鲁,谢谢。它就像一个魅力。出于好奇,这是一个循环,是否还有矢量化版本?
  • 我不认为有一个简单的矢量化函数可以做到这一点。这里的另一个解决方案更像是一种“矢量化”方法——尽管两者基本上做同样的事情。我倾向于使用显式循环而不是使用 &lt;&lt;- 运算符。您可能想使用microbenchmark 来比较它们的速度。
  • 我将它们与 proc.time 的速度进行了比较:在超过 100 万条记录和 3 种模式上,两者都花费了大约 35 秒。你的要快一点。但是,我尝试了 800 种模式(是的)然后它在内存中回显。另一个例子虽然有效
  • @mauricevergeer 实际上,这让我思考 - 见上面的修正 - 我意识到毕竟有一个矢量化函数 - outer。可能更快。
  • 哇,快多了。 proctime 从 28 秒降至 2 秒。谢谢!
【解决方案2】:

这与安德鲁的答案基本相同,但我还是发布了它:

lapply(vecpat, function(x){
    mydata[x] <<- as.numeric(grepl(x, mydata$text))
})
ID  text aaa bbb ccc ddd eee
1  6   aaa   1   0   0   0   0
2  7   bbb   0   1   0   0   0
3 10   ccc   0   0   1   0   0
4 11 a bbb   0   1   0   0   0
5 29 a bbb   0   1   0   0   0
6 30   bbb   0   1   0   0   0
7 31   ddd   0   0   0   1   0

看到更新,我又试了几个。在我的环境中,这是最快的:

library(stringi)
cbind(mydata, sapply(vecpat, function(x) stri_detect_fixed(mydata$text, x) + 0L))

【讨论】:

  • 亲爱的 amatsuo_net,谢谢!,它工作得很好,就像我之前对我问题的回复一样。
猜你喜欢
  • 2021-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-01
  • 1970-01-01
  • 2021-03-18
  • 1970-01-01
相关资源
最近更新 更多