我正在寻找帮助在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_split
,gsub
或sub
正常工作,主要是因为我最终只删除|
或全部字符串,但最后|
和之后。
我希望这是有道理的,谢谢!
答案 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
我在第一个|
之后保留了剩下的部分,但如果你不需要它,你也可以删除它。