开发者

How to search for patterns that are not exactly same each time?

I have a list like this:

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

The searching patter in this case is "any-number cut". Thus, to visualize the list in a better way, the list is in the following pattern

"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)"

I want place the "before items" to column 1, until it found another "any number cut" pattern, and put the "after items" to column 2. The final results would as follows:

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

Could experts teach me how to do it with R? I learn from previous stackoverflow messages that R can search for fixed items (e.g. cut) and strsplit them into different cells. The challenge here (to me) is the searching pattern is changing that the number before开发者_StackOverflow the word "cut" is different for each of them. what is the most efficient way to search and cut it in the right place using R?


The following works with your example data:

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

First, create a regex pattern to use with grep: The following pattern searches for digits (\d) followed by a space and the word cut. See ?regexp and ?grep for details.

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
)

The results:

      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

I will leave it as an exercise to you to do the cleanup of the data in column 1. Hint: Use str_extract in package stringr. You can refer to this question: How can I use back references with `grep` in R? for examples of how to do this. Further hint, your patterns should be something like "(.*) \\d* cut".


Below we use x to represent your list variable. " \d+ cut$" matches any string with space, digits, space and cut at the end so that no.cut is a logical vector that is TRUE for each component of x with no cut. We then pick out the first word of each component by removing the first space and everything after it. This gives first.word. Finally we replace each component of first.word with NA if it has no cut and use na.locf from the zoo package to move the remaining words (the ones that were not replaced by NA) forward into the NA spots to give us the tentative before vector. We use first.word as the tentative after vector. The positions corresponding to no.cut in the tentative before and after vectors form the required result. This works with your example data. Depending on the precise nature of your actual data you may need to revise some of this slightly; however, the overall pattern of the solution should still hold.

> 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"
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜