天下苦正则久矣,尤其当字符串中有自己想要的一段数据时候苦苦提取不出来的感觉真是难受,今天给大家介绍3个R包来解决这种正则带来烦恼的包,希望对大家能有所帮助。
regexplain
RegExplain是一个RStudio插件,用于正则表达式。以交互方式构建regexp、检查常用字符串匹配函数的输出、查阅交互式帮助页面或使用包含的资源学习正则表达式。
github地址:https://github.com/gadenbuie/regexplain
安装
# install.packages("remotes")
remotes::install_github("gadenbuie/regexplain")
安装完成后,Addins处会多出一些插件,其中常用的就是RegExplain Selection和RegExplain File功能,即可以将文本导入RegExplain的两种方法。
在RStudio窗口中中选择对象名称或文本行或代码行,然后运行RegExplain Selection即可。
要从文件中导入文本,请使用RegExplain file来导入要用正则表达式处理的文本。在导入文本时,RegExplain自动将文本缩减为唯一的条目,并限制行数。
另外也有CheetSheet辅助我们查看基本正则的写法。
RegExplain也提供了函数view_regex,您可以使用它作为字符串::str_view()的替换。除了突出显示文本中匹配的部分之外,view_regex()还会为组着色,并尝试为regex表达式本身着色。
text <- c("breakfast=eggs;lunch=pizza",
"breakfast=bacon;lunch=spaghetti",
"no food here")
pattern <- "((\\w+)=)(\\w+).+(ch=s?p)"
view_regex(text, pattern)
详情查看Github,有较详细的示例..
stringr.plus
github地址:https://github.com/johncassil/stringr.plus
stringr.plus提供了一些stringr中没有的额外函数来处理字符串。函数运行可以很好的与tidyverse搭配。这些函数在处理url和文件路径数据时特别有用,可以从字符串中提取特定的文本。
示例
#install.packages('stringr.plus')
#remotes::install_github("johncassil/stringr.plus")
library(stringr.plus)
url <- 'www.carfax.com/vehicle/3GCPKTE77DG348900'
#仅提取基本的url
str_extract_before(string = url, pattern = '/')
#> [1] "www.carfax.com"
## 提取基础url的后面的部分
str_extract_after(string = url, pattern = '/')
#> [1] "vehicle/3GCPKTE77DG348900"
## 仅提取最后一部分
str_extract_after(string = url, pattern = 'vehicle/')
#> [1] "3GCPKTE77DG348900"
## 提取最后一部分的前5个字母
str_extract_after(string = url, pattern = 'vehicle/', num_char = 5)
#> [1] "3GCPK"
##通过last 和 first(默认) 更方便的指定
str_extract_after(string = url, pattern = '/', which = "last")
#> [1] "3GCPKTE77DG348900"
str_extract_before(string = url, pattern = '/', which = "last")
#> [1] "www.carfax.com/vehicle"
## 提取两个格式之间的文本
file_path <- "C:/Users/pingu/Downloads/a-very-poorly-named-file_08_09_2020.csv"
str_extract_between(string = file_path, pattern1 = '_', pattern2 = ".csv")
#> [1] "08_09_2020"
有时,检测字符串是否包含多个模式是有帮助的,str_detect_multiple通常用于过滤目的,或与且的概念。
############### 且模式#######
#str_detect_multiple with the "and" 方法确保文本中含有多个匹配默认
file_path <- "C:/Users/pingu/Downloads/a-very-poorly-named-file_08_09_2020.csv"
str_detect_multiple(string = file_path, patterns = c("pingu", "2020"), method = 'and')
#> [1] TRUE
#更精简版的模式 str_detect_multiple_and()
str_detect_multiple_and(string = file_path, patterns = c("Downloads", "csv"))
#> [1] TRUE
############### 或模式 #######
#str_detect_multiple with the "and" 方法确保文本中含有多个匹配默认
str_detect_multiple(string = file_path, patterns = c("very", "purple"), method = 'or')
#> [1] TRUE
#It is also aliased with str_detect_multiple_or()
str_detect_multiple_or(string = file_path, patterns = c("large", "file"))
#> [1] TRUE
理解模式匹配的上下文也很重要,str_extract_context可以将模式扩展为给定模式前后的最大字符数
## 使用window_size函数控制字符数
## str_extract_context()返回第一个匹配
sentence <- "I have spread my dreams under your feet; Tread softly because you tread on my dreams."
str_extract_context(string = sentence, pattern = "my", window_size = 15)
#> [1] "I have spread my dreams under y"
##str_extract_context_all() 返回所有的匹配
str_extract_context_all(string = sentence, pattern = "my", window_size = 15)
#> [,1]
#> [1,] "I have spread my dreams under y"
#> [2,] "e you tread on my dreams."
interregex
inferregex的目标是推断识别字符串的正则表达式(regex)以及其他特性,这点还是很智能的。
github地址:https://github.com/daranzolin/inferregex
example1-单字符串
remotes::install_github("daranzolin/inferregex")
library(inferregex)
s <- "abcd-9999-ab9"
infer_regex(s)$regex
#> [1] "^[a-z]{4}-\\d{4}-[a-z]{2}\\d$"
example2-批量多字符串
library(purrr)
(regex_df <- map_dfr(rownames(mtcars), infer_regex))
all(map2_lgl(regex_df$string, regex_df$regex, ~grepl(.y, .x)))
#> string regex
#> 1 Mazda RX4 ^[A-Z][a-z]{4}\\s[A-Z]{2}\\d$
#> 2 Mazda RX4 Wag ^[A-Z][a-z]{4}\\s[A-Z]{2}\\d\\s[A-Z][a-z]{2}$
#> 3 Datsun 710 ^[A-Z][a-z]{5}\\s\\d{3}$
#> 4 Hornet 4 Drive ^[A-Z][a-z]{5}\\s\\d\\s[A-Z][a-z]{4}$
#> 5 Hornet Sportabout ^[A-Z][a-z]{5}\\s[A-Z][a-z]{9}$
#> 6 Valiant ^[A-Z][a-z]{6}$
#> 7 Duster 360 ^[A-Z][a-z]{5}\\s\\d{3}$
#> 8 Merc 240D ^[A-Z][a-z]{3}\\s\\d{3}[A-Z]$
#> 9 Merc 230 ^[A-Z][a-z]{3}\\s\\d{3}$
#> 10 Merc 280 ^[A-Z][a-z]{3}\\s\\d{3}$
#> 11 Merc 280C ^[A-Z][a-z]{3}\\s\\d{3}[A-Z]$
#> 12 Merc 450SE ^[A-Z][a-z]{3}\\s\\d{3}[A-Z]{2}$
#> 13 Merc 450SL ^[A-Z][a-z]{3}\\s\\d{3}[A-Z]{2}$
#> 14 Merc 450SLC ^[A-Z][a-z]{3}\\s\\d{3}[A-Z]{3}$
#> 15 Cadillac Fleetwood ^[A-Z][a-z]{7}\\s[A-Z][a-z]{8}$
#> 16 Lincoln Continental ^[A-Z][a-z]{6}\\s[A-Z][a-z]{10}$
#> 17 Chrysler Imperial ^[A-Z][a-z]{7}\\s[A-Z][a-z]{7}$
#> 18 Fiat 128 ^[A-Z][a-z]{3}\\s\\d{3}$
#> 19 Honda Civic ^[A-Z][a-z]{4}\\s[A-Z][a-z]{4}$
#> 20 Toyota Corolla ^[A-Z][a-z]{5}\\s[A-Z][a-z]{6}$
.........
all(map2_lgl(regex_df$string, regex_df$regex, ~grepl(.y, .x)))
#> [1] TRUE
可以看到,掌握了这三个R包后(可能后两个帮助会更大一些),遇到类似情况可以轻松提取数据或者直接交给函数识别出该模式正则的写法,即提高了分析效率,又对正则的写法有所收获,两全其美,快哉快哉~