如何搜索每次不完全相同的模式?

时间:2011-06-02 06:17:09

标签: r search

我有一个这样的清单:

 list <- c("xxx 23 cut", "yyy", "zzz", "www 55 cut", "kkk", "ggg", "yyy", "eee 7 cut", "ccd" )

这种情况下的搜索模式是“任意数字切割”。因此,为了以更好的方式可视化列表,列表采用以下模式

"before item (=xxx) "  "any number cut (= 23 cut)"
"after item (=yyy)"
"after item (=zzz)"
"before item (=www) "  "any number cut (= 55 cut)"
"after item (=kkk)"
"after item (=ggg)"
"after items (=yyy)"
"before item (=eee) "  "any number cut (= 7cut)"
"after item (=cce)"

我想将“之前的项目”放在第1列,直到找到另一个“任意数字切割”模式,然后将“之后的项目”放到第2列。最终结果如下:

xxx yyy
xxx zzz
www kkk
www ggg
www yyy
eee ccd

专家可以教我如何使用R吗?我从以前的stackoverflow消息中学到了R可以搜索固定项目(例如剪切)并将它们分成不同的单元格。这里(对我来说)的挑战是搜索模式正在改变,“切割”一词之前的数字对于它们中的每一个都是不同的。使用R在正确的地方搜索和剪切它的最有效方法是什么?

2 个答案:

答案 0 :(得分:6)

以下内容适用于您的示例数据:

x <- c("xxx 23 cut", "yyy", "zzz", "www 55 cut", "kkk", "ggg", "yyy", "eee 7 cut", "ccd" )

首先,创建一个regex模式以与grep一起使用:以下模式搜索数字(\ d),后跟空格和单词cut。有关详细信息,请参阅?regexp?grep

cut_pattern <- "\\d* cut"

cut_positions <- grep(cut_pattern, x)
cut_repeat <- c(cut_positions[-1], length(x) + 1) - cut_positions -1
before_items <- rep(x[cut_positions], times=cut_repeat)
after_items <- x[!grepl(cut_pattern, x)]

data.frame(
    before = before_items,
    after  = after_items
)

结果:

      before after
1 xxx 23 cut   yyy
2 xxx 23 cut   zzz
3 www 55 cut   kkk
4 www 55 cut   ggg
5 www 55 cut   yyy
6  eee 7 cut   ccd

我将把它留作练习来清理第1列中的数据。提示:在包str_extract中使用stringr。您可以参考此问题:How can I use back references with `grep` in R?,了解如何执行此操作的示例。进一步提示,您的模式应该类似于"(.*) \\d* cut"

答案 1 :(得分:3)

下面我们使用x来表示您的list变量。 “\ d + cut $”匹配任何带有空格,数字,空格和最后剪切的字符串,以便no.cut是一个逻辑向量,对于x的每个组件都是TRUE,没有剪切。然后我们通过删除第一个空格及其后的所有内容来挑选每个组件的第一个单词。这给出了first.word。最后,如果first.word没有剪切,我们将NA的每个组件替换为na.locf,并使用动物园包中的NA来移动剩余的单词(未被{{1}替换的单词})转到NA点,给我们一个暂定的before向量。我们使用first.word作为暂定after向量。在暂定no.cutbefore向量中与after对应的位置构成了所需的结果。这适用于您的示例数据。根据您的实际数据的确切性质,您可能需要稍微修改一些;但是,解决方案的整体模式仍应保持不变。

> library(zoo)
> no.cut <- !grepl(" \\d+ cut$", x)
> first.word <- sub(" .*", "", x)
> cbind(before = na.locf(replace(first.word, no.cut, NA)), 
+  after = first.word)[no.cut, ]
     before after
[1,] "xxx"  "yyy"
[2,] "xxx"  "zzz"
[3,] "www"  "kkk"
[4,] "www"  "ggg"
[5,] "www"  "yyy"
[6,] "eee"  "ccd"