tidyverse —— stringr包

浏览: 1977

stringr包,顾名思义,处理字符串专用包,本篇笔记对它进行简单介绍。提到字符串处理,有一个绕不过去的主题,它是字符串处理的利器,也是字符串处理的问题制造机,它就是——正则表达式。本篇笔记顺带介绍一下正则表达在R语言中的应用。

1.  连接字符串

在base包中,字符串的连接主要用paste和paste0两个函数,在stringr包中,它们的替代品是str_c()函数。举个简单的例子:

str_c("x", "y","z")
str_c("x", "y", sep =", ")

image.png

str_c()继承R语言函数的矢量化运算风格,会对参数进行循环计算,直到更长的那个参数的完结:

str_c("", c("a","b", "c"), "-suffix")

image.png


2.  截取子集

要截取字符串中的一段,使用str_sub()函数。str_sub()函数接受两个数字参数作为截取字段起止的位置。不同于Python等其他语言的索引从0开始,R语言从1开始计数,并且包含截止的位置。举个例子:

x <- c("Apple","Banana", "Pear")

str_sub(x, 1, 3)
str_sub(x, -3, -1)

image.png

负数表示从字符串的右边开始进行截取。


3.  正则表达式

好了,开始我最喜欢也最头疼的正则表达部分。先说通配符“.”,它能够匹配除了新行外的所有字符,那么如果想要匹配它本身,就需要对它进行转义。在其他诸如stata中,我们在之前加上反斜杠“\”表示转义,但是,在R语言中,我们使用字符串的形式来表示匹配模式,而在字符串中“\”本身是有特殊用法的字符,需要对它进行转义来表示转义,就需要加两个反斜杠。比如下面这个例子,我们用str_view函数来显示匹配结果:

str_view(c("abc", "a.c","bef"), "a\\.c")

image.png

如上图,双反斜线转义后才能匹配字符串中的“.”。

那么对于反斜线“\”本身呢?我们要怎么匹配它?

大家可能会觉得,转义要两个反斜杠,再加上本身一个,要三个反斜杠。

image.png

真这么简单我何必特意问出来。

答案是要4个。

大家在R语言中设置当前路径的时候,如果在路径中使用了反斜杠,就需要写两个“\”,前一个表示转义,因为反斜杠本身在字符串中有特殊的含义,所以转义是必须的。同理,在R语言中,文本中要表示“\”,需要两个反斜杠“\\”来表示。而要构建一个正则模式来匹配文本中的这两个反斜杠“\\”,首先是这两个反斜杠得有,就是两个,再注意一下,匹配模式本身也是文本,在文本中要表达一个反斜杠,就要在之前多加一个,所以在原有的两个反斜杠前各加一个反斜杠,就一共有四个。就像这样:

x <- "a\\b"
str_view(x, "\\\\")

image.png

好啦,除了这一点需要特别点出来,R语言中的正则就和其他Perl啊、Python啊啥的语言一样,大致没什么特别的了。接下来介绍相关的函数。


4.  探测匹配

4.1 str_detect函数

str_detect函数用来探测是否在字符串中匹配到给定的模式,返回布尔值来表示结果。用words这个数据集,我们来匹配一下以“ac”开头的单词:

head(words)
head(str_detect(words, "^ac"))

image.png

“^”表示只匹配行开头的部分,与之相对的是“$”,表示只匹配行的结尾部分。

计算一下words中以元音字母结尾的单词的比例:

mean(str_detect(words, "[aeiou]$"))

image.png

中括号“[]”表示匹配其中的任意元素,“[^]”则表示匹配除了中括号里的元素外的所有元素。比如上代码还可以表示为1减去以辅音字母结尾的单词比例:

1 - mean(str_detect(words, "[^aeiou]$"))

image.png

4.2 str_count函数

str_count函数用来计数给定的模式被匹配上了多少次。比如计算words中每个单词中有多少个元音字母:

head(words)
head(str_count(words, "[aeiou]"))

image.png


5.  提取匹配

5.1 str_extract函数

有时候我们不仅想要知道匹配了多少次,还想知道具体匹配到了什么,这时候就可以用str_extract函数。以sentences数据为例,我们想要知道含有颜色的句子有哪些,都含有哪些颜色:

color_match <- str_c("red","orange", "yellow", "green", "blue","purple", sep = "|")
has_color <- str_subset(sentences,color_match)
matches <- str_extract(has_color,color_match)
head(matches)

image.png

str_extract函数只提取第一个匹配值,如果要匹配所有,就用str_extract_all函数。

more <- sentences[str_count(sentences,color_match) > 1]
str_extract_all(more, color_match)

image.png

返回的结果是一个列表,可以用tidyr包的unnest函数修整成tibble格式的数据,也可以设置simplify = TRUE来返回一个矩阵:

str_extract_all(more, color_match, simplify= TRUE)

image.png

5.2 str_match函数

str_match函数在需要提取多个匹配值时非常趁手。比如想要匹配sentences中的名词,我们假定名词前都有冠词the/a/an中的一个,其后跟一个空格,再跟一个非空格的元素组,那么我们给出如下的匹配模式:

noun <- "(the|a|an) ([^ ]+)"

()表示匹配模式组别,“+”表示前一个匹配值出现超过一次。我们需要提取的有两个匹配值,一个是第一个括号里的冠词,一个是第二个括号里的名词。

has_noun <- sentences %>% str_subset(noun)%>% head(10)
has_noun %>% str_extract(noun)
has_noun %>% str_match(noun)

image.png

对比str_extract函数把两个匹配值提取成一个字符串,str_match把我们要的冠词和名词分别列出。str_match也只匹配第一个,如果要提取所有的名词和冠词,可以用str_match_all函数。


6.  替换匹配

str_replace函数替换匹配到的第一个模式,str_replace_all则可以替换所有。比如:

x <- c("1 house", "2 cars", "3 people")
str_replace_all(x, c("1" = "one", "2" ="two", "3" = "three"))

image.png


7.  拆分

str_split函数将字符串向量进行拆分,以sentences数据为例,按空格进行拆分:

sentences %>% head(5) %>% str_split("", simplify = T)

image.png

同样可以进行字符串拆分并且可以使用正则表达式的还有之前讲到的tidyr包的separate函数。


8.  其他模式

在R语言中,使用一个字符串格式的模式时,是自动调用正则表达式的。如果想要匹配的内容不需要调用正则就能解决,就可以使用fixed函数,来避免烦人的转义,而且也更省时。比如,如果要匹配文本中的反斜杠,配合fixed函数只用两个反斜杠就行了:

a <- 'hello\\wor\\ld'
writeLines(a)
str_extract_all(a, fixed('\\'))

image.png

而如果要匹配的内容非常繁琐,则可以选择设置comments = TRUE,这样可以在正则模式中添加注释,比如Hadley的例子:

phone <- regex("
\\(? # optional opening parens
(\\d{3}) # area code
[)- ]? # optional closingparens, dash, or space
(\\d{3}) # another threenumbers
[ -]? # optional space or dash
(\\d{3}) # three more numbers
", comments = TRUE)
str_match("514-791-8141",phone)

image.png

一个小tip,fixed和regex函数都有ignore _case选项,设置为TRUE后可以无视大小写进行匹配。



最后,附上stringr包的cheatsheet下载地址,想要了解更多的盆友们可以看看:

https://github.com/rstudio/cheatsheets/raw/master/strings.pdf

推荐 0
本文由 野菜团子 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册