使用 stringr 处理字符串(一)

R
数据处理
stringr
Author

Rui

Published

November 8, 2022

参考 Hadley Wickham 的 R for Data Science (R数据科学)。开源版本:https://r4ds.had.co.nz/

Tip

虽然不少处理字符串的工作使用 base R 中的函数就可以完成,但我更推荐使用 stringr 中的函数。一方面可以使你的代码更加 tidy,另一方面:stringr 中的函数都有共同的前缀 “str_”,在你不太记得函数的具体名称时只要在 RStudio 中输入函数前缀 “str_”,RStudio 就可以为你自动补齐。

Code
library(stringr)
library(tidyverse)
Note

虽然 stringrtidyverse 生态中的一员,但它并不是 tidyverse 的核心包,所以需要手动加载 stringr

字符串基础

字符串的创建

可以使用双引号(英文)来创建字符串:

Code
string1 <- "I Love R"
print(string1)
## [1] "I Love R"

英文字母大小写转换

base R 中:

Code
toupper(string1)
## [1] "I LOVE R"
tolower(string1)
## [1] "i love r"

stringr 中:

Code
str_to_upper(string1)
## [1] "I LOVE R"
str_to_lower(string1)
## [1] "i love r"

字符串长度

Code
length(string1)
## [1] 1

为什么返回的是 1?因为 length() 函数求的是向量的长度,它把 string1 当作是只包含一个元素的字符串向量,所以返回的结果是 1。

base R 中使用 nchar() 求字符串的长度,注意空格也是一个字符串。

Code
nchar(string1)
## [1] 8

也可以使用 stringr 中的 str_length()

Code
str_length(string1)
## [1] 8

字符串拼接

base R 中使用 paste()paste0() 函数。

stringr 中使用 str_c() 函数:

Code
str_c("x", "y")
## [1] "xy"
str_c("x", "y", "z")
## [1] "xyz"

可以使用 sep 参数指定拼接时的分隔符:

Code
str_c("x", "y", sep = "-")
## [1] "x-y"

而且 str_c() 是向量化的函数,它可以对长度较短的向量循环补齐以匹配较长的向量:

Code
str_c(c("I", "You", "We"), "Love", "R", sep = " ")
## [1] "I Love R"   "You Love R" "We Love R"

必须对缺失值保持警觉,和很多其他函数一样,缺失值 NA 是可传染的。如果想让它直接输出为 “NA” ,可以使用 str_replace_na()

Code
x <- c("x", NA)
str_c(x, "y", sep = "-")
## [1] "x-y" NA
str_c(str_replace_na(x), "y", sep = "-")
## [1] "x-y"  "NA-y"

长度为 0 的字符串将会被悄无声息地丢弃。但要注意的是:虽然长度为 0 的字符串会被丢弃,但与其相连的分隔符却会被保留。

Code
str_c("I", "Love", "", sep = " ")
## [1] "I Love "

若要将字符串向量中的所有元素合并地话,可以使用 collapse() 参数。但特别要注意 sepcollapse 联用的情况:

Code
str_c(c("I", "Love", "R"), collapse = "-")
## [1] "I-Love-R"
str_c(c("I", "You"), "Love R", sep = " ", collapse = " and ")
## [1] "I Love R and You Love R"

从上面这个例子来看:sep 的优先度比 collapse 要高。

字符串索引(取子集)

base R 中的 substr() 函数可以使用我们指定的起点和终点对字符串取子集:

Code
substr(string1, start = 1, stop = 5)
## [1] "I Lov"
substr(string1, 1, 5) # 简写
## [1] "I Lov"

或者使用 stringr 中的 str_sub() 函数:

Code
str_sub(string1, start = 1, end = 5)
## [1] "I Lov"
str_sub(string1, 1, 5) # 简写
## [1] "I Lov"

如果 end 参数比 start 参数小,则返回一个空字符串:

Code
str_sub(string1, 5, 1)
## [1] ""

str_sub() 同样也是一个向量化的函数:

Code
x <- c("Apple", "Banana", "Pear")
str_sub(x, 1, 3)
## [1] "App" "Ban" "Pea"

其中的 endstart 参数还可以接受负数,表示从后往前索引:

Code
str_sub(x, -3, -1)
## [1] "ple" "ana" "ear"

利用该函数还可以实现就地改值:

Code
str_sub(x, 1, 1) <- str_to_lower(str_sub(x, 1, 1))
x
## [1] "apple"  "banana" "pear"

其他一些函数

当字符串非常长时,可以使用 str_wrap() 函数自动换行(它的功能不止如此,主要是让字符串的输出更加整洁):

Code
x <- "我在朦胧中,眼前展开一片海边碧绿的沙地来,上面深蓝的天空中挂着一轮金黄的圆月。我想:希望是本无所谓有,无所谓无的。这正如地上的路;其实地上本没有路,走的人多了,也便成了路。"
cat(str_wrap(x, width = 40))
## 我在朦胧中,眼前展开一片海边碧绿的沙地
## 来,上面深蓝的天空中挂着一轮金黄的圆月。
## 我想:希望是本无所谓有,无所谓无的。这
## 正如地上的路;其实地上本没有路,走的人多
## 了,也便成了路。

str_trim() 函数可以去除字符串头、尾部的空白:

Code
x <- "  I love R  "
str_trim(x)
## [1] "I love R"

可以指定移除字符串头部还是尾部还是首尾两端的空白:

Code
str_trim(x, side = "left")
## [1] "I love R  "
str_trim(x, side = "both")
## [1] "I love R"

下一节

下一节中,将会介绍处理字符串的利器——正则表达式。内容主要包括:正则表达式基础、使用正则表达式进行模式匹配、stringr 中相关的函数。