1

我正在寻求帮助在 R 中实现一个函数来截断level_stream我在 R 中的数据帧的字符串向量,但还没有太多运气。本质上,当列中的一行pre_quiz_score不是NA时,我想截断字符串的开始部分直到(包括)第一个字符,如果 a不是该行|,我想截断最后一个字符之后的所有内容。|post_quiz_scoreNA

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, orsub正常工作,主要是因为我最终只删除了|'s 或所有字符串,但最后一个|和之后。

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

4

4 回答 4

4

我们可以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

于 2016-12-20T04:47:14.367 回答
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
于 2016-12-20T03:49:23.217 回答
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
于 2016-12-20T04:13:32.673 回答
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

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

于 2016-12-20T04:29:15.607 回答