抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

数据除了数值类型之外,还有着其它的数据类型,字符串就是其中之一。除了基本的操作之外,正则表达式( regular expression ,regexp )也是重要的相关内容之一。tidyverse 包中用于字符串处理的包是 stringr

字符串基础

字符串和特殊字符创建

可以使用英文的单引号 ' 或双引号 " 包裹文本来创建字符串。

推荐使用双引号创建字符串

对于在 R 中具有特殊含义的字符,可以使用转义来使特殊字符正常储存:

名称符号
单引号\'
双引号\"
反斜线\\
换行符\n
制表符\t

可以使用 ?"'"?'"' 查看完整的特殊字符列表

字符串的储存形式和打印形式不相同,因此可以使用 print()writeLines() 函数分别打印字符串的原始内容和转义后内容:

字符串打印
1
2
3
4
5
6
> "\""
# [1] "\""
> print("\"")
# [1] "\""
> writeLines("\"")
# "

字符串长度

可以使用 str_length() 函数查看字符串中的字符数量。

使用该方法查看长度时,计算的是转义后的字符数量

字符串组合

可以使用 str_c() 函数将多个字符串组合。该函数会将给出的多个参数前后连接,当参数中存在字符向量时,会使用循环机制(向量化)进行补全。

可以使用 sep 参数指定各参数拼接时所使用的连接符,以字符的形式给出。默认为 "" ,即不含连接符。

当参数中包含缺失值 NA 时,与其相关的结果都会变成 NA 。可以使用 str_replace_na() 函数将缺失值 NA 或字符向量中的缺失值 NA 转换为字符 "NA" 。

当参数中包含 0 长度对象时,str_c() 函数会将其舍弃。

str_c() 函数的这个特性经常与短 if 语句结合使用

可以使用 collapse 参数指定结果字符向量进一步拼接时所使用的连接符,以字符的形式给出。默认为 NULL ,即不进行向量内拼接。

对于两个拼接参数,可以参考以下示例:

1
2
3
4
5
6
7
8
> str_c(c("x", "y", "z"), c("a", "b", "c", "d", "e", "f"))
# [1] "xa" "yb" "zc" "xd" "ye" "zf"
> str_c(c("x", "y", "z"), c("a", "b", "c", "d", "e", "f"), sep = ".")
# [1] "x.a" "y.b" "z.c" "x.d" "y.e" "z.f"
> str_c(c("x", "y", "z"), c("a", "b", "c", "d", "e", "f"), collapse = ":")
# [1] "xa:yb:zc:xd:ye:zf"
> str_c(c("x", "y", "z"), c("a", "b", "c", "d", "e", "f"), sep = ".", collapse = ":")
# [1] "x.a:y.b:z.c:x.d:y.e:z.f"

字符串取子集

可以使用 str_sub() 函数提取字符串中的一部分。该函数的基本形式为 str_sub(string, start = 1L, end = -1L) ,表示提取出字符串 string 中的第一个字符开始,到最后一个字符结束的全部字符。startend 参数接受整型向量作为索引。

使用该方法提取字符串时,即使索引超出边界,也不会提示错误,而是尽可能地把符合要求的内容提取出来

除了提取字符串,该函数还可以用来给字符串的指定位置赋值。其基本形式为 str_sub(string, start = 1L, end = -1L, omit_na = FALSE) <- value ,表示将字符串 string 中的第一个字符开始,到最后一个字符结束的全部字符,替换为 value 中的字符。

区域设置

大部分的字符串函数中都有一个参数 locale 用来指定区域,该参数接受一个字符串,内容为 2 或 3 个字母的缩写语言编码。区域设置可以参考 ISO 639 语言编码标准。

正则表达式

可以使用 str_view(string, pattern, match = NA)str_view_all(string, pattern, match = NA) 来获取字符向量 string 中符合模式 pattern 的部分,因此适合用来说明正则表达式在 R 中的应用。match 参数接受 NATRUEFALSE 三个值,分别对应显示全部单词、匹配单词和不匹配单词。

视情况可能需要下载安装并加载 htmltoolshtmlwidgets

基础匹配

  1. 精确匹配:

    1
    2
    > x <- c("alpha", "beta", "gamma")
    > str_view(x, "eta")
    精确匹配
    精确匹配
  2. 单字匹配:

    1
    2
    > x <- c("alpha", "beta", "gamma")
    > str_view(x, ".a.")
    单字匹配
    单字匹配

对于具有特殊意义的字符,需要使用转义字符来表达其原有字符含义。但由于正则表达式和 R 本质上是两个不同的系统,因此起到转义作用的反斜线 \ 本身也需要进行转义。所以对于特殊字符,有:

  • 一般转义字符:例如单字匹配符号 . ,若只想表达英文句号的原有含义,需要通过 R 和 正则表达式的两层转义,因此在 R 中应使用 \\. 来表示
  • 反斜线:对于转义符号 \ ,若只想表达反斜线的原有含义,那么在正则表达式上应使用 \\ 来进行第一层转义,在 R 上使用 \\\\ 来对两个反斜线进行第二层转义

一般讨论正则表达式时,不会考虑 R 的第二层转义。因此

锚点

可以使用 ^$ 来分别表示字符串的开头和末尾,这在正则表达式中被称为锚点

1
2
3
> x <- c("alpha", "beta", "gamma")
> str_view(x, "^a")
> str_view(x, "a$")
开头匹配
开头匹配
末尾匹配
末尾匹配

通过联合使用 ^$ 来匹配完整字符串。

字符类

  • \d 可以匹配任意数字
  • \s 可以匹配任意空白字符(空格、制表符和换行符等)
  • [abc] 可以匹配 a 、b 或 c 。
  • [^abc] 可以匹配除 a 、b 、c 外的任意字符

字符选项

  • | 表示模式或
  • () 括起表示模式优先级分组

重复

表示重复的符号需要在前面添加一个字符或用括号括起的多个字符来表示重复的内容。

  • ? 表示重复 0 次或 1 次
  • + 表示重复 1 次或多次
  • * 表示重复 0 次或多次

此外,还可以使用以下方式精确匹配重复次数

  • {n} 表示匹配 n 次
  • {n,} 表示最少匹配 n 次
  • {,m} 表示最多匹配 m 次
  • {n,m} 表示匹配 n 到 m 次

问号 ? 也可用在重复模式符号后,问号的有无表示匹配模式的最短字符串或最长字符串

分组与回溯引用

可以使用括号 () 来给模式中的符号分组,编号自前向后开始从 1 计数。在同个模式中可以使用反斜线加数字的模式来表示之前已分组的符号,这个特性叫做回溯引用。例如 “(abc)(ijk)(lmn)\3\2\1” 和 “abcijklmnlmnijkabc” 是等同的。

上例是指正则表达式的写法,在 R 中还需要对回溯引用做额外的转义,即 (abc)(ijk)(lmn)\3\2\1

对于分组内包括单字匹配或重复等情况,使用回溯引用则表示该处的匹配和分组的匹配完全一致。例如 (…)\1 表示任意三个字符重复两次,而不是任意六个字符

工具

除了 str_view() 函数,还有许多 stringr 函数可以使用正则表达式来解决各种问题。和 str_view()str_view_all() 函数的关系一样, stringr 函数都有单个匹配和所有匹配两种函数模式,区别在于函数名末尾是否带有 _all

匹配检测

可以使用 str_detect() 函数来确定一个字符向量是否匹配一种模式,该函数返回一个与输入向量具有同样长度的逻辑向量。

由于函数的返回值为逻辑向量,因此可以使用 sum() 函数计数,使用 mean() 函数计算比例,使用逻辑值取子集的方式提取指定元素

可以使用 str_subset() 函数来提取出给定字符向量中匹配模式的元素,该函数返回一个字符向量。

可以使用 str_count() 函数来返回字符串中匹配的数量。

匹配不会重叠,因此字符串中符合模式的数量与匹配模式的次数可能并不相等

提取匹配内容

可以使用 str_extract() 函数来提取出给定字符向量中首个匹配模式的字符,该函数返回一个与输入向量具有同样长度的字符向量,不匹配的元素的对应返回值为 NA 。其变种 str_extract_all() 函数会提取出所有匹配,并返回与输入向量相同长度的字符列表。该函数的所有匹配版本具有 simplify 参数,指定该参数的值为 TRUE 可以使返回的值变为矩阵。该矩阵的列数与最大匹配数量相同,匹配数量不足的元素的匹配内容会按从左向右的顺序排列,其余位置以 "" 填充。

分组匹配

可以使用 str_match() 函数来提取出给定字符向量中首个匹配模式的字符,并且给出匹配中分组的内容。该函数返回一个矩阵,其行数与输入向量长度相等,列数比匹配模式中的分组数多 1 。其中第一列为匹配模式的字符,其他列为匹配模式内对应分组的字符。

此外,若输入向量为 tibble ,那么还可以使用 tidyr::extract() 函数来完成上述操作。其基本结构为 extract(data, col, into, regex = "([[:alnum:]]+)", remove = TRUE, convert = FALSE, ...) 。该函数会将 tibble 数据框 datacol 列的内容里匹配 regex 模式对应分组的字符赋给 into 向量的名称列,并附在原数据框 data 之后。

替换匹配

可以使用 str_replace() 函数将匹配内容替换为新字符串。除了给定字符向量和匹配模式之外,还接受一个与给定字符向量或匹配模式长度相等的字符向量作为匹配模式部分的替换值。也可以省略掉匹配模式和替换字符向量,将两者以 匹配模式 = 替换字符 的键值对向量给出。

可以使用分组和回溯引用的方式来使用替换匹配以达到交换的作用

拆分

可以使用 str_split() 函数将字符串拆分成多个片段。其基本结构为 str_split(string, pattern, n = Inf, simplify = FALSE) 。该函数会将字符串 string 中匹配模式 pattern 的部分作为分界将原字符串拆开,并舍弃掉匹配模式的部分。参数 nsimplify 分别表示拆分片段的最大数量和输出方式(列表或矩阵)。默认为不限数量和列表形式。

除了正则表达式,模式还支持使用 boundary() 函数来指定边界模式。

匹配内容定位

可以使用 str_locate()str_locate_all() 函数获得每个匹配的开始位置和结束位置。

其他模式

匹配模式在以字符串的形式给出时,R 默认会调用 regex() 函数将其包装。当进行显式调用时,可以指定以下参数控制匹配方式:

  • 设定 ignore_case = TRUE 可以使匹配模式变为大小写不敏感(大小写由区域设置控制)
  • 设定 multiline = TRUE 可以使锚点以行为单位,而不是以完整字符串为单位
  • 设定 comments = TRUE 可以在正则表达式中加入注释和空白字符

除了正则表达式 regex() 函数,还可以使用以下函数:

  • fixed() 函数可以按照字符串的字节形式进行精确匹配
  • coll() 函数可以按照标准排序功能比较字符串,可以使用 locale 参数来指定其它地区的排序功能
  • boundary() 函数可以进行边界匹配

其他应用

  • 可以使用 apropos() 函数在全局环境空间中搜索所有可用对象,常用来检索函数名称
  • 可以使用 dir() 函数列出目录下的所有文件,指定其中的 patten 参数可以筛选出匹配模式的文件名

stringi

每个 stringr 函数都有首个匹配和所有匹配两种模式,以函数名是否含有 _all 区分。同样地,由于 stringr 是将 stringi 中常用的函数提取出来进行简化使用,因此部分 stringr 不能完成的任务,可以使用 stringi 完成。每个 stringr 函数都有对应的 stringi 函数,以开头是 str_ 还是 stri_ 进行区分。并且 stringi 函数中还有着大量未被简化进 stringr 中的函数。

评论



This is a picture without description

This is a picture without description This is a picture without description This is a picture without description