在 R 中使用正则表达式进行字符串拆分和截断
String Splitting and Truncating using Regular Expressions in R
我正在寻求帮助,在 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
正常工作,主要是因为我最终只删除了 |
或除最后一个 |
和之后的所有字符串。
我希望这是有道理的,谢谢!
按照您所说的执行逻辑即可:
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
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
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
我保留了第一个 |
之后的剩余部分,但如果您不需要,也可以将其删除。
我们可以使用 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 表示它)
我正在寻求帮助,在 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
正常工作,主要是因为我最终只删除了 |
或除最后一个 |
和之后的所有字符串。
我希望这是有道理的,谢谢!
按照您所说的执行逻辑即可:
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
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
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
我保留了第一个 |
之后的剩余部分,但如果您不需要,也可以将其删除。
我们可以使用 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 表示它)