使用R中的正则表达式进行字符串拆分和截断

时间:2016-12-20 03:21:48

标签: r regex stringr strsplit tidyverse

我正在寻找帮助在R中实现一个函数来截断R中我的数据帧的level_stream字符串向量,并且还没有太多运气。基本上当pre_quiz_score列中的行不是NA时,我想截断字符串的开头部分直到(并包括)第一个|字符,我想要截断如果该行的|不是post_quiz_score,那么所有内容都会超过最后一个NA字符。

df <- data.frame(ls = c('123 L0=38/42|425 L0=40/42', NA, '482 L7=7/12|789 L8=5/6|523 L9=2/6'), 
                 pre_quiz_score = c(88, NA, 12), 
                 post_quiz_score = c(NA, NA, 90))

我希望以“tidyverse”的方式实现它,并将其向量化以获得类似

的内容
----------------------------------------------------------------------------
|                 ls                  | pre_quiz_score | post_quiz_score   |
| 425 L0=40/42                        | 88             | NA                |
| NA                                  | NA             | NA                |
| 789 L8=5/6                          | 12             | 90                |

到目前为止,我还没有让stringr::str_splitgsubsub正常工作,主要是因为我最终只删除|或全部字符串,但最后|和之后。

我希望这是有道理的,谢谢!

4 个答案:

答案 0 :(得分:3)

按照你的说法实施逻辑:

library(stringi)
library(dplyr)

df <- data.frame(ls = c('123 L0=38/42|425 L0=40/42', NA, '482 L7=7/12|789 L8=5/6|523 L9=2/6'),
                 pre_quiz_score = c(88, NA, 12),
                 post_quiz_score = c(NA, NA, 90),
                 stringsAsFactors=FALSE)


df %>%
  mutate(ls=ifelse(!is.na(pre_quiz_score),
                   stri_replace_first_regex(ls, "^[[:alnum:][:blank:]=/]+\\|", ""), ls),
         ls=ifelse(!is.na(post_quiz_score),
                   stri_replace_last_regex(ls, "\\|[[:alnum:][:blank:]=/]+$", ""), ls))
##             ls pre_quiz_score post_quiz_score
## 1 425 L0=40/42             88              NA
## 2         <NA>             NA              NA
## 3   789 L8=5/6             12              90

答案 1 :(得分:3)

我们可以使用sub

中的base R
df$ls <- sub("^[^|]+\\|([^|]+).*", "\\1", df$ls)
df
#            ls pre_quiz_score post_quiz_score
#1 425 L0=40/42             88              NA
#2         <NA>             NA              NA
#3   789 L8=5/6             12              90

说明

我们从字符串的开头(|)匹配一个或多个不是[^|]+^)的字符,然后是|(转义它 - \\|,因为它是元字符),然后捕获一个或多个不是|作为一个组的字符(即在括号([^|]+)内),后跟字符,直到结束字符串(.*)并将其替换为捕获的组的后向引用(\\1 - 因为只有一个捕获组,它是第一个,我们用1表示它)

答案 2 :(得分:2)

library(dplyr)
df %>% mutate(ls = sapply(strsplit(df$ls, "\\|"), function(x) x[2]))

#            ls pre_quiz_score post_quiz_score
#1 425 L0=40/42             88              NA
#2         <NA>             NA              NA
#3   789 L8=5/6             12              90

答案 3 :(得分:0)

tidyr::separate()允许您将列拆分为子列。使用extra = "drop"参数,它最多只能保留length(into)列。

library(tidyr)
separate(df, ls, c("remove", "keep"), sep="\\|", extra = "drop")

#>         remove         keep pre_quiz_score post_quiz_score
#> 1 123 L0=38/42 425 L0=40/42             88              NA
#> 2         <NA>         <NA>             NA              NA
#> 3  482 L7=7/12   789 L8=5/6             12              90

我在第一个|之后保留了剩下的部分,但如果你不需要它,你也可以删除它。