中文字幕理论片,69视频免费在线观看,亚洲成人app,国产1级毛片,刘涛最大尺度戏视频,欧美亚洲美女视频,2021韩国美女仙女屋vip视频

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
《R數(shù)據(jù)科學(xué)》第10章-用stringr處理字符串
  • 1. 準(zhǔn)備工作

  • 2. 字符串基礎(chǔ)

    • 2.1 創(chuàng)建字符串或字符向量

    • 2.2 字符串長度:str_length() 函數(shù)

    • 2.3 字符串組合:str_c() 函數(shù)

    • 2.4 字符串取子集:str_sub() 函數(shù)

    • 2.5 區(qū)域設(shè)置

  • 3. 用正則表達(dá)式進(jìn)行模式匹配:str_view()函數(shù)

    • 3.1 基礎(chǔ)匹配

    • 3.2 錨點(diǎn)

    • 3.3 字符類與字符選項(xiàng)

    • 3.4 重復(fù)

    • 3.5 分組與回溯引用

  • 4. 工具

    • 4.1 匹配檢測:str_detect() 函數(shù)

    • 4.2 提取匹配內(nèi)容:str_extract() 函數(shù)

    • 4.3 分組匹配:str_match() 函數(shù)

    • 4.4 替換匹配內(nèi)容:str_replace() 函數(shù)

    • 4.5 拆分:str_split() 函數(shù)

    • 4.6 定位匹配內(nèi)容:str_locate()

  • 5. 其他類型的模式

    • 5.1 regex() 函數(shù)

    • 5.2 fixed() 函數(shù)

    • 5.3 coll() 函數(shù)

    • 5.4 boundary() 函數(shù)

  • 6. 正則表達(dá)式的其他應(yīng)用

    • 6.1 apropos() 函數(shù)

    • 6.2 dir() 函數(shù)

  • 7. stirngi

1. 準(zhǔn)備工作

stringr 不是tidyverse 核心 R 包的一部分,故需要使用命令來加載它。

library(tidyverse)
library(stringr)

2. 字符串基礎(chǔ)

2.1 創(chuàng)建字符串或字符向量

(1)用單引號或雙引號來創(chuàng)建字符串。

單引號和雙引號在 R中沒有區(qū)別。一般用雙引號。單引號通常用于分隔包含"的字符向量。

string1 <- "This is a string" #用"創(chuàng)建字符串
string2 <- 'To put a "quote" inside a string, use single quotes' #字符串中含"時(shí),用"來創(chuàng)建字符串

如果要在字符串中包含一個'或",需要用 \ 對其進(jìn)行“轉(zhuǎn)義”(也就是說,\在字符串中有特殊含義,即“轉(zhuǎn)義”):

> writeLines("\'") # writelines() 函數(shù)用于查看字符串的初始內(nèi)容
'
> writeLines('\"')
"

如果要在字符串中包含一個反斜杠,需要用兩個反斜杠:\。

> writeLines('\\')
\

其他特殊字符列表(用 ?'"' 或 ?"'" 命令來查看) 

> writeLines("\u00b5")
μ

(2)用 c() 函數(shù)來創(chuàng)建字符向量(包含多個字符串)

> c("one", "two", "three")
[1] "one" "two" "three"

2.2 字符串長度:str_length() 函數(shù)

  • 功能:返回字符串中的字符數(shù)量:

  • 用法:str_length(string)

> str_length(c("a", "R for data science", NA))
[1] 1 18 NA

2.3 字符串組合:str_c() 函數(shù)

(1)str_c() 函數(shù)-stringr包中的函數(shù)

  • 功能:將多個字符串連接成一個字符串。

  • 用法:str_c(..., sep = "", collapse = NULL)

  • 參數(shù) ... :字符串列表或字符向量

  • 參數(shù) sep :分隔符,默認(rèn)不分隔

  • 參數(shù) collapse :將字符向量中的字符串合并,并用提供的分隔符分隔

> str_c("x", "y", "z") # 輸入為3個字符串"x", "y", "z"
[1] "xyz"

> str_c("x", "y", "z", sep = ", ") # 用“逗號+空格”分隔
[1] "x, y, z"

> str_c(c("x", "y", "z"), collapse = ", ") # 輸入為1個字符向量c("x", "y", "z")
[1] "x, y, z"
  • 長度為 0 的對象會被丟棄,這與 if 結(jié)合起來特別有用

name <- "Hadley"
time_of_day <- "morning"
birthday <- TRUE
str_c(
"Good ", time_of_day, " ", name,
if (birthday) " and HAPPY BIRTHDAY",
"."
)
[1] "Good morning Hadley and HAPPY BIRTHDAY."

> birthday <- FALSE
> str_c(
+ "Good ", time_of_day, " ", name,
+ if (birthday) " and HAPPY BIRTHDAY",
+ "."
+ )
[1] "Good morning Hadley."
  • str_c() 函數(shù)是向量化的,它可以自動循環(huán)短向量,使得其與最長的向 量具有相同的長度:

> str_c("prefix-", c("a", "b", "c"), "-suffix") # "prefix-" "-suffix"是短向量,c("a", "b", "c")是長向量
[1] "prefix-a-suffix" "prefix-b-suffix" "prefix-c-suffix"
  • 缺失值是可傳染的。如果想要將它們輸出為 "NA",可以使用 str_ replace_na():

> x <- c("abc", NA) # 1個字符向量,包含2個字符串
> str_c("|-", x, "-|") # 組合字符串,沒有特殊說明時(shí),缺失值可傳染
[1] "|-abc-|" NA
> str_c("|-", str_replace_na(x), "-|") # str_replace_na()將缺失值輸出為 "NA",
[1] "|-abc-|" "|-NA-|"

(2) paste() 和 paste0() 函數(shù)-R語言內(nèi)置函數(shù)

  • 功能:連接字符串

  • 用法:

  • paste (..., sep = " ", collapse = NULL, recycle0 = FALSE) #可自定義分隔符,默認(rèn)為空格

  • paste0(..., collapse = NULL, recycle0 = FALSE) #字符串間緊密連接

> x <- "apple"
> y <- "banana"
> paste(x,y)
[1] "apple banana"
> paste0(x,y)
[1] "applebanana"
  • 處理NA時(shí)與str_c()的區(qū)別:str_c()中NA有傳染性,paste()將NA返回成字符

> x <- "apple"
> z <- NA
> paste(x,z)
[1] "apple NA"
> str_c(x,z)
[1] NA

2.4 字符串取子集:str_sub() 函數(shù)

  • 功能:提取或修改字符串的一部分。

  • 用法:str_sub(string, start = 1L, end = -1L)

  • 參數(shù)start和end:Start給出第一個字符的位置(默認(rèn)為第一個),end給出最后一個字符的位置(默認(rèn)為最后一個字符)。

> x <- c("Apple", "Banana", "Pear")
> str_sub(x, 1, 3)
[1] "App" "Ban" "Pea"
  • 即使字符串過短, str_sub() 函數(shù)也不會出錯,它將返回盡可能多的字符:

> str_sub("a", 1, 5)
[1] "a"
  • 用 str_sub()替換字符串:通過 函數(shù)的賦值形式來實(shí)現(xiàn)

> str_sub(x, 1, 1) <- str_to_lower(str_sub(x, 1, 1)) # str_to_lower()將文本轉(zhuǎn)化為小寫
> x
[1] "apple" "banana" "pear"

2.5 區(qū)域設(shè)置

(1)str_to_upper(),str_to_title()

  • 功能:將文本轉(zhuǎn)化為大寫

  • 用法:str_to_upper(string, locale = "en")

  • 參數(shù)locale:區(qū)域設(shè)置,默認(rèn)為“en”(英語)。區(qū)域設(shè)置可以參考 ISO 639 語言編碼標(biāo)準(zhǔn),語言編碼是 2 或 3 個字母的縮寫,見下表,如“tr”(土耳其語) 

> str_to_upper(c("i", "?"), locale = "tr") # 土耳其語中有帶點(diǎn)和不帶點(diǎn)的兩個i,它們在轉(zhuǎn)換為大寫時(shí)是不同的:
[1] "?" "I"
> str_to_upper(c("i", "?")) #默認(rèn)區(qū)域設(shè)置是英語,轉(zhuǎn)化成大寫時(shí)是一樣的
[1] "I" "I"

(2) str_sort() 和 str_order() 函數(shù)

  • 功能:排序

  • 參數(shù)locale:區(qū)域設(shè)置

> x <- c("apple", "eggplant", "banana")
> str_sort(x, locale = "en") # 英語
[1] "apple" "banana" "eggplant"
> str_sort(x, locale = "haw") # 夏威夷語
[1] "apple" "eggplant" "banana"
# 用英語和夏威夷與排序時(shí)的結(jié)果是不一樣的

3. 用正則表達(dá)式進(jìn)行模式匹配:str_view()  函數(shù)

正則表達(dá)式(Regular Expression)

是用事先定義好的一些特定字符、及這些特定字符的組合,組成一個“規(guī)則字符串”,這個“規(guī)則字符串”用來表達(dá)對字符串的一種過濾邏輯。描述了一種字符串匹配的模式(pattern)。通常被用來檢索、替換那些符合某個模式(規(guī)則)的文本。許多程序設(shè)計(jì)語言都支持利用正則表達(dá)式進(jìn)行字符串操作

str_view() 和 str_view_all() 函數(shù)

  • 用法:

str_view(string, pattern, match = NA) 顯示第一個匹配

str_view_all(string, pattern, match = NA) 顯示所有匹配

  • 參數(shù)match:為TRUE時(shí)只顯示匹配項(xiàng),為FALSE時(shí)只顯示不匹配項(xiàng),為NA時(shí)顯示匹配項(xiàng)和不匹配項(xiàng)(默認(rèn))

  • 要顯示str_view()匹配的結(jié)果,還需要額外安裝兩個 R 包:htmltools 和 htmlwidgets。

  • 很多 stringr 函數(shù)都是成對出現(xiàn)的:一 個函數(shù)用于單個匹配,另一個函數(shù)用于全部匹配,后者會有后綴 _all。

# htmltools包可以用 library() 直接安裝
library(htmltools)

# htmlwidgets包直接安裝不,可以試著用下面命令安裝
BiocManager::install("htmlwidgets")
library(htmlwidgets)
  • str_view()匹配的結(jié)果顯示在右下角窗格中

3.1 基礎(chǔ)匹配

(1) 精確匹配字符串

> x <- c("apple", "banana", "pear")
> str_view(x, "an")

(2)用.可以匹配任意字符(除了換行符)(但只能匹配1個字符):

> str_view(x, ".a.")

(3)如何匹配字符 . 呢?

. 可以匹配任意字符,正則表達(dá)式用\來去除某些字符的特殊含義,因此,要匹配.,需要的正則表達(dá)式是\.(前面加1個\來去除.匹配任意字符的特殊含義,使其僅用來匹配.)。

\ 在字符串中也用作轉(zhuǎn)義字符(去除某些字符的特殊含義),因此,正則表達(dá)式 \. 的字符串形式應(yīng)是 \\.

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

(4)如何匹配\呢?

要匹配\,需要的正則表達(dá)式是\\,對應(yīng)的字符串形式為"\\\\"

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

3.2 錨點(diǎn)

默認(rèn)情況下,正則表達(dá)式會匹配字符串的任意部分。

需要從字符串的開頭或末尾進(jìn)行匹配時(shí),要設(shè)置錨點(diǎn)。

  • ^ 從字符串開頭進(jìn)行匹配。

  • $ 從字符串末尾進(jìn)行匹配。

x <- c("apple", "banana", "pear")
str_view(x, "^a") # 匹配字符串開頭的a
str_view(x, "a$") # 匹配字符串末尾的a

x <- c("apple pie", "apple", "apple cake")
str_view(x, "apple") #正則表達(dá)式默認(rèn)匹配字符串的任意部分,只要含apple即可,這里3個字符串中的apple都會匹配到
str_view(x, "^apple$") #嚴(yán)格匹配到第2個字符串,不僅含apple,且字符串以a開頭以e結(jié)尾
  • \b 匹配單詞間的邊界

x <- c("The green light in the brown box flickered.","Glue the sheet to the dark blue background.","Hedge apples may stain your hands green." )
# 匹配x中的顏色
colors <- c("red", "orange", "yellow", "green", "blue", "purple") # 創(chuàng)建顏色名稱向量
color_match <- str_c(colors, collapse = "|") # 將顏色名稱向量轉(zhuǎn)化為正則表達(dá)式
str_view_all(x,color_match) # 匹配x中的顏色
# 發(fā)現(xiàn)第一個句子中的flickered也被匹配到了,該怎么修改?
color_match2 <- str_c("\\b(",color_match,")\\b") # pattern前后加\b(單詞邊界)
str_view_all(x,color_match2)

3.3 字符類與字符選項(xiàng)

很多特殊模式可以匹配多個字符。(雖然可以匹配多個,但是一次只匹配一個,想匹配多次見3.4)

  • .可以匹配除換行符外的任意字符。

  • \d 可以匹配任意數(shù)字。

  • \s 可以匹配任意空白字符(如空格、制表符和換行符)

  • [abc] 可以匹配 a、 b 或 c。

  • [^abc] 可以匹配除 a、 b、 c 外的任意字符。

注意:要想創(chuàng)建包含 \d 或 \s 的正則表達(dá)式,需要在字符串中對 \ 進(jìn)行轉(zhuǎn)義,因此需 要輸入 "\\d" 或 "\\s"。

| 的優(yōu)先級很低(最后才考慮|),所以 abc|xyz 匹配的是 abc 或 xyz,而不是 abcyz 或 abxyz。

如果優(yōu)先級讓人感到困惑,那么可以使用括號讓其表達(dá)得更清晰一些:如gr(e|a)y匹配的是grey或gray。

3.4 重復(fù)

正則表達(dá)式的另一項(xiàng)強(qiáng)大功能是,其可以控制一個模式能夠匹配多少次。(是將它前面的字符匹配多少次)

  • ?:0 次或 1 次。相當(dāng)于{0,1}

  • +:1 次或多次。相當(dāng)于{1,}

  • *:0 次或多次。相當(dāng)于{0,}

x <- "1888 is the longest year in Roman numerals: MDCCCLXXXVIII"
str_view(x, "CC?") #"CC?"是將第2C匹配0次或1次,也就是說匹配的是CCC
str_view(x, "CC+") #"CC+"是將第2C匹配1次或多次,也就是說匹配的是連續(xù)2個以上的C
str_view(x, 'C[LX]+') #'C[LX]+'是將[LX]匹配1次或多次,[LX]意思是匹配LX,也就是說只要C后面接的是LX都可以匹配到,直到不是LX為止。

注意:這些運(yùn)算符的優(yōu)先級非常高(也就是說優(yōu)先考慮匹配次數(shù)),因此很多時(shí)候需要使用括號

> x <- c("color","colour","banana","bananana")
> str_view(x, "banana+", match = TRUE) #"banana+"是將最后一個a匹配1次或多次,匹配的是bananabananaaaa..,這里只能匹配到第3個和第4個字符串中的banana
> str_view(x, "bana(na)+", match = TRUE) #"bana(na)+"是將最后的na匹配1次或多次,比如bananabananana,這里第3個和第4個字符串可以全部匹配到

還可以精確設(shè)置匹配的次數(shù)

  • {n}:匹配 n 次。

  • {n,}:匹配 n 次或更多次。

  • {,m}:最多匹配 m 次。

  • {n, m}:匹配 n 到 m 次。

> x <- "1888 is the longest year in Roman numerals: MDCCCLXXXVIII"
> str_view(x, "C{2}") #"C{2}"是將C匹配2次,即匹配的是CC
> str_view(x, "C{2,}") #"C{2,}"是將C匹配2次以上,也就是說可以匹配連續(xù)2個以上的C
> str_view(x, "C{2,3}") #"C{2,3}"是將C匹配2~3次,也就是說匹配的是CCCCC

正則表達(dá)式默認(rèn)會匹配盡量長的字符串(默認(rèn)的匹配方式是“貪婪的”,如果有長的就匹配長的,沒長的就匹配略短的)。

在正則表達(dá)式后面加一個 ?,可以將匹配方式更改為“懶惰的”,即匹配盡量短的字符串。

> str_view(x, "C{2,3}") #"C{2,3}"匹配方式為貪婪,如果字符串含CCC,那匹配的是CCC而非CC。當(dāng)然,如果只有2個連續(xù)C那匹配的就是CC,如果有4個連續(xù)C那匹配的還是前3C
> str_view(x, "C{2,3}?") #"C{2,3}?"匹配方式為懶惰,即匹配的是CC
> str_view(x, 'C[LX]+?') #'C[LX]+?'匹配方式為懶惰,即匹配的是CLCX

練習(xí)

用語言描述以下正則表達(dá)式匹配的是何種模式(仔細(xì)閱讀來確認(rèn)我們使用的是正則表達(dá)式,還是定義正則表達(dá)式的字符串)?
a. ^.*$ #這是正則表達(dá)式,.*表示重復(fù)0次以上的.,這里^$表示以任意字符開始,以任意字符結(jié)束,故這個匹配的是任意字符。
b. "\\{.+\\}" #這是定義正則表達(dá)式的字符串,由于{}在正則表達(dá)式中有特殊含義,所以\\{匹配的是單純的{,\\}匹配的是},.+表示重復(fù)1次以上的.,.在正則表達(dá)式中可匹配任意字符,故這個匹配的是任意花括號里有至少1個字符的字符串,如"{a}""{abc}"
c. \d{4}-\d{2}-\d{2} #這是正則表達(dá)式,\d可以匹配任意數(shù)字,{4}意思是將任意數(shù)字匹配4次,故這個匹配的是4位數(shù)字后接一個連字符,然后是兩個數(shù)字后接一個連字符,然后是另外兩個數(shù)字。這是一個正則表達(dá)式,可以匹配格式為“YYYY-MM-DD(%Y-%m-%d)的日期。如2021-08-16
d. "\\\\{4}" #這是定義正則表達(dá)式的字符串,正則表達(dá)式的字符串中\\\\匹配的是\,故這個匹配的是\\\\。

找出以 3 個輔音字母開頭的單詞
str_view(words,"^[^aeiou]{3}",match=TRUE) #這里[^aeiou]可以匹配任意非元音字母(輔音字母),但只能匹配一個字母,{3}是匹配3次輔音字母

找出有連續(xù) 3 個或更多元音字母的單詞。
str_view(words,"[aeiou]{3}",match=TRUE)

找出有連續(xù) 2 個或更多元音—輔音配對的單詞
str_view(words,"([aeiou][^aeiou]){2,}",match=TRUE)

3.5 分組與回溯引用

括號的作用:

  • 闡明優(yōu)先級,用于消除復(fù)雜表達(dá)式中的歧義。【前部分】

  • 能對正則表達(dá)式進(jìn)行分組,分組可以在匹配時(shí)回溯引用(如 \1、 \2 等)【本部分】

  • 提取一個復(fù)雜匹配的各個 部分【后部分】

回溯引用

  • 回溯引用可以匹配到捕獲組曾經(jīng)匹配過的結(jié)果。

  • 回溯引用的標(biāo)志是反斜杠后加數(shù)字

  • 回溯引用中的數(shù)字是從左至右計(jì)算的。回溯引用中的\1對應(yīng)第一個圓括號中的內(nèi)容,\2對應(yīng)第二個圓括號中的內(nèi)容。

# 找出名稱中有重復(fù)的一對字母的所有水果
str_view(fruit, "(..)\\1", match = TRUE) #"(..)\\1"..表示匹配任意兩個字符,\1表示回溯引用第一個()中的內(nèi)容,由于用字符串表示,所以表示為\\1,故這個匹配的是名稱中有重復(fù)的一對字母的所有水果

練習(xí)

用語言描述以下正則表達(dá)式會匹配何種模式?
(.)\1\1 #同一字符重復(fù)3次,如"aaa"
"(.)(.)\\2\\1" #一對字符鏡像出現(xiàn),如"abba"
(..)\1 #任意2個字符重復(fù),如"a1a1"
"(.).\\1.\\1" #注意這是定義正則表達(dá)式的字符串,表示“一個字符后面跟著任意字符,原始字符,任何其他字符,再重復(fù)原始字符”,如"abaca""b8b.b",即一共5個字符,第1、3、5個字符一樣,其余隨意。
"(.)(.)(.).*\\3\\2\\1" 表示“三個字符,后面跟著0個或多個任
字符,后面跟著三個相同的字符,只是順序相反”,如“abcsgasgddsadgsdgcba”或“abccba”或“abc1cba”。

4. 工具

基本思想:將一個復(fù)雜問題分解為多個簡單問題

4.1 匹配檢測:str_detect() 函數(shù)

(1)str_detect() 函數(shù)

  • 功能:確定一個字符向量能否匹配一種模式,判斷的是能否匹配,故結(jié)果是邏輯向量,即TRUE或FALSE

  • 用法:str_detect(string, pattern, negate = FALSE),negate為TRUE 則返回不匹配的元素

# 判斷x3個字符串中是否含e
> x <- c("apple", "banana", "pear")
> str_detect(x, "e")
[1] TRUE FALSE TRUE
> str_detect(x, "e", negate = TRUE)
[1] FALSE TRUE FALSE
  • 從數(shù)學(xué)意義上來說,邏輯向量中的 FALSE 為 0, TRUE 為 1。這使得在匹配特別大的向量時(shí),sum() 和 mean() 函數(shù)能夠發(fā)揮更大的作用:

# t開頭的常用單詞有多少個?
> sum(str_detect(words, "^t")) # words中共有980個單詞,其中以t開頭的有65個,也就是說str_detect(words, "^t")的結(jié)果中有65TRUE(數(shù)學(xué)意義上=1),915FALSE(數(shù)學(xué)意義上=0),6519150的和為65。
[1] 65
# sum(..., na.rm = FALSE)函數(shù)中的...可以是數(shù)字,也可以是邏輯向量

# 以元音字母結(jié)尾的常用單詞的比例是多少?
> mean(str_detect(words, "[aeiou]$")) # words中共有980個單詞,其中以元音字母結(jié)尾的有271個,也就是說str_detect(words, "^t")的結(jié)果中有271TRUE(數(shù)學(xué)意義上=1),709FALSE(數(shù)學(xué)意義上=0),27117090的均值為0.2765306。
[1] 0.2765306
  • str_detect() 函數(shù)的一種常見用法是選取出匹配某種模式的元素。

# 通過邏輯取子集方式,來選取出匹配某種模式的元素
# [是取子集函數(shù),調(diào)用方式為x[i],邏輯向量取子集方式可提取出TRUE值對應(yīng)的所有元素(見課本15.4.5向量取子集)
> words[str_detect(words, "x$")] #提取出 words 中str_detect(words, "x$")結(jié)果為TRUE(以x結(jié)尾)的元素
[1] "box" "sex" "six" "tax"

# 或用str_subset() 包裝器函數(shù),來來選取出匹配某種模式的元素
> str_subset(words, "x$")
[1] "box" "sex" "six" "tax"
  • 如果正則表達(dá)式過于復(fù)雜,則應(yīng)該將其分解為幾個更小的子表達(dá)式,將每個子表達(dá)式的匹配結(jié)果賦給一個變量,并使用邏輯運(yùn)算組合起來。

# 找出以 x 開頭或結(jié)尾的所有單詞

# 用str_subset()函數(shù)選取匹配某種模式的元素
> str_subset(words,"^x|x$") # words中沒有以x開頭的單詞,以x結(jié)尾的單詞有4個
[1] "box" "sex" "six" "tax"

# 通過邏輯取子集方式選取匹配某種模式的元素
> words[str_detect(words,"^x|x$")] #選出 words 中結(jié)果為TRUE的元素
[1] "box" "sex" "six" "tax"

# 將其分解為2個簡單問題,將結(jié)果賦值給變量,然后使用邏輯運(yùn)算組合起來
> start_with_x <- str_detect(words,"^x")
> end_with_x <- str_detect(words,"x$")
> words[start_with_x|end_with_x]
[1] "box" "sex" "six" "tax"
  • 字符串通常會是數(shù)據(jù)框的一列,此時(shí)我們可以使用 filter 操作

> df <- tibble(word = words, i = seq_along(word)) #seq_along()用于生成序列,df是一個數(shù)據(jù)框(2個向量,一個word,一個序號)
> df %>% filter(str_detect(words, "x$")) #篩選出dfwordx結(jié)尾的行
# A tibble: 4 x 2
word i
<chr> <int>
1 box 108
2 sex 747
3 six 772
4 tax 841

(2)str_count()函數(shù)

  • 功能:返回字符串中匹配的數(shù)量

  • 用法:str_count(string, pattern = "")

> x <- c("apple", "banana", "pear")
> str_count(x, "a") # 返回字符串中a的個數(shù)
[1] 1 3 1

> mean(str_count(words, "[aeiou]")) # str_count(words, "[aeiou]")返回words中每個單詞中含元音字母的個數(shù),求均值即為“平均來看,每個單詞中含元音字母的個數(shù)”
[1] 1.991837

# 哪個單詞包含最多數(shù)量的元音字母?
> vowels <- str_count(words, "[aeiou]")
> words[which(vowels == max(vowels))]
[1] "appropriate" "associate" "available" "colleague" "encourage" "experience"
[7] "individual" "television"

# 哪個單詞包含最大比例的元音字母? (提示:分母應(yīng)該是什么?)
> prop_vowels <- str_count(words, "[aeiou]") / str_length(words)
> words[which(prop_vowels == max(prop_vowels))]
[1] "a"
  • str_count() 也完全可以同 mutate() 函數(shù)一同使用

> df %>% mutate(vowels = str_count(word, "[aeiou]"), consonants = str_count(word, "[^aeiou]")) #df基礎(chǔ)上添加2vowelsconsonants,表示每個單詞中含元音字母和輔音字母的個數(shù)
# A tibble: 980 x 4
word i vowels consonants
<chr> <int> <int> <int>
1 a 1 1 0
2 able 2 2 2
3 about 3 3 2
4 absolute 4 4 4
5 accept 5 2 4
6 account 6 3 4
7 achieve 7 4 3
8 across 8 2 4
9 act 9 1 2
10 active 10 3 3
# ... with 970 more rows

注意:匹配從來不會重疊。

> str_count("abababa", "aba") # "abababa"中,模式 "aba" 會匹配2次,而不是3
[1] 2

4.2 提取匹配內(nèi)容:str_extract() 函數(shù)

  • 功能:提取匹配的實(shí)際文本

# 找出包含一種顏色的所有句子
> colors <- c("red", "orange", "yellow", "green", "blue", "purple") #創(chuàng)建一個顏色名稱向量
> color_match <- str_c(colors, collapse = "|") #將顏色名稱向量轉(zhuǎn)換成一個正則表達(dá)式
> has_color <- str_subset(sentences, color_match) #選取出包含一種顏色的句子
> matches <- str_extract(has_color, color_match) #從選取出的句子中提取出顏色
> head(matches) #顯示前6個匹配結(jié)果
[1] "blue" "blue" "red" "red" "red" "blue"
  • str_extract(string, pattern) 只提取第一個匹配

  • str_extract_all(string, pattern, simplify = FALSE) 可以提取全部匹配。

# 邏輯向量取子集方式一般與比較函數(shù)結(jié)合起來使用效果更佳,提取出TRUE值對應(yīng)的所有元素(見課本15.4.5向量取子集)
> (more <- sentences[str_count(sentences, color_match) > 1])
[1] "It is hard to erase blue or red ink."
[2] "The green light in the brown box flickered."
[3] "The sky in the west is tinged with orange red."
-
# str_extract() 只提取第一個匹配
> str_extract(more, color_match)
[1] "blue" "green" "orange"

# str_extract() 可以提取全部匹配,并返回為一個列表
> str_extract_all(more, color_match)
[[1]]
[1] "blue" "red"

[[2]]
[1] "green" "red"

[[3]]
[1] "orange" "red"
  • str_extract_all()的參數(shù) simplify 默認(rèn)為FALSE,返回字符向量列表;如果為TRUE,則返回一個字符矩陣,其中較短的匹配會擴(kuò)展到與最長的匹配具有同樣的長度:

# simplify = TRUE,返回一個矩陣
> str_extract_all(more, color_match, simplify = TRUE)
[,1] [,2]
[1,] "blue" "red"
[2,] "green" "red"
[3,] "orange" "red"

# 較短的匹配會擴(kuò)展到與最長的匹配具有同樣的長度
> x <- c("a", "a b", "a b c")
> str_extract_all(x, "[a-z]", simplify = TRUE)
[,1] [,2] [,3]
[1,] "a" "" ""
[2,] "a" "b" ""
[3,] "a" "b" "c"

練習(xí)

Harvard sentences 數(shù)據(jù)集中提取以下內(nèi)容。
a. 每個句子的第一個單詞。
pattern <- "[A-Za-z][A-Za-z']*"
b. ing 結(jié)尾的所有單詞。
pattern <- "\\b[A-Za-z]+ing\\b"
c. 所有復(fù)數(shù)形式的單詞。
pattern <- "\\b[A-Za-z]{3,}s\\b"

4.3 分組匹配:str_match() 函數(shù)

  • 功能:可以給出每個獨(dú)立分組。

  • 用法:

  • str_match(string, pattern)

  • str_match_all(string, pattern)

  • 結(jié)果:str_match() 返回的不是字符向量,而是一個矩陣,其中一列是完整匹配,后面的列是每個分組的匹配:

# 用括號來提取一個復(fù)雜匹配的各個部分
> noun <- "(a|the) ([^ ]+)"
> has_noun <- sentences %>% str_subset(noun) %>% head(10)

# str_extract()函數(shù)可以給出完整匹配,返回的是字符向量
> has_noun %>% str_extract(noun)
[1] "the smooth" "the sheet" "the depth" "a chicken" "the parked" "the sun" "the huge"
[8] "the ball" "the woman" "a helps"

# str_match()函數(shù)則可以給出每個獨(dú)立分組,返回的是一個矩陣,其中一列是完整匹配,后面的列是每個分組的匹配:
> has_noun %>% str_match(noun)
[,1] [,2] [,3]
[1,] "the smooth" "the" "smooth"
[2,] "the sheet" "the" "sheet"
[3,] "the depth" "the" "depth"
[4,] "a chicken" "a" "chicken"
[5,] "the parked" "the" "parked"
[6,] "the sun" "the" "sun"
[7,] "the huge" "the" "huge"
[8,] "the ball" "the" "ball"
[9,] "the woman" "the" "woman"
[10,] "a helps" "a" "helps"
  • 如果數(shù)據(jù)是保存在 tibble 中的,那么使用 tidyr::extract() 會更容易。這個函數(shù)的工作方式 與 str_match() 函數(shù)類似,只是要求為每個分組提供一個名稱,以作為新列放在 tibble 中:

# tidyr::extract()的第一個參數(shù)是數(shù)據(jù)框,第2個參數(shù)是列名,第3個參數(shù)是正則表達(dá)式,remove = TRUE表示從輸出數(shù)據(jù)幀中移除輸入列。
> tibble(sentence = sentences) %>% tidyr::extract(sentence, c("article", "noun"), "(a|the) ([^ ]+)", remove = FALSE )
# A tibble: 720 x 3
sentence article noun
<chr> <chr> <chr>
1 The birch canoe slid on the smooth planks. the smooth
2 Glue the sheet to the dark blue background. the sheet
3 It's easy to tell the depth of a well. the depth
4 These days a chicken leg is a rare dish. a chicken
5 Rice is often served in round bowls. NA NA
6 The juice of lemons makes fine punch. NA NA
# ... with 714 more rows

4.4 替換匹配內(nèi)容:str_replace() 函數(shù)

  • 功能:用新字符串替換匹配內(nèi)容

  • 用法:str_replace(string, pattern, replacement) replacement表示替換的字符向量,即把pattern匹配到的內(nèi)容替換為replacement

  • 用法1:用固定字符串替換匹配內(nèi)容(replacement為固定字符串)

> x <- c("apple", "pear", "banana")
> str_replace(x, "[aeiou]", "-") #x中的第1個元音字母替換為-
[1] "-pple" "p-ar" "b-nana"
> str_replace_all(x, "[aeiou]", "-") #x中的所有元音字母替換為-
[1] "-ppl-" "p--r" "b-n-n-"
  • 用法2:通過提供一個命名向量,使用 str_replace_all() 函數(shù)可以同時(shí)執(zhí)行多個替換

> x <- c("1 house", "2 cars", "3 people")
> str_replace_all(x, c("1" = "one", "2" = "two", "3" = "three"))
[1] "one house" "two cars" "three people"
  • 用法3:用回溯引用來插入匹配中的分組

# 交換句子中第二個單詞和第三個單詞的順序
> sentences %>%
+ str_replace("([^ ]+) ([^ ]+) ([^ ]+)", "\\1 \\3 \\2") %>%
+ head(3)
[1] "The canoe birch slid on the smooth planks." "Glue sheet the to the dark blue background."
[3] "It's to easy tell the depth of a well."

練習(xí)

(1) 使用反斜杠替換字符串中的所有斜杠。
str_replace_all("past/present/future", "/", "\\\\")

(2) 使用 replace_all() 函數(shù)實(shí)現(xiàn) str_to_lower() 函數(shù)的一個簡單版。
replacements <- c("A" = "a", "B" = "b", "C" = "c", "D" = "d", "E" = "e", "F" = "f", "G" = "g", "H" = "h", "I" = "i", "J" = "j", "K" = "k", "L" = "l", "M" = "m", "N" = "n", "O" = "o", "P" = "p", "Q" = "q", "R" = "r", "S" = "s", "T" = "t", "U" = "u", "V" = "v", "W" = "w", "X" = "x", "Y" = "y", "Z" = "z")
lower_words <- str_replace_all(words, pattern = replacements)
head(lower_words)

(3) 交換 words 中單詞的首字母和末尾字母,其中哪些字符串仍然是個單詞?
swapped <- str_replace_all(words, "^([A-Za-z])(.*)([A-Za-z])$", "\\3\\2\\1")
intersect(swapped, words)

4.5 拆分:str_split() 函數(shù)

  • 功能:將字符串拆分為多個片段

  • 用法:

  • str_split(string, pattern, n = Inf, simplify = FALSE)

  • str_split_fixed(string, pattern, n)

  • 參數(shù)simplify:默認(rèn)為FALSE,返回的是列表;為TRUE時(shí)返回矩陣

# 將句子拆分成單詞
# simplify默認(rèn)為FALSE,返回的是列表
> sentences %>% head(3) %> str_split(" ") #在空格處拆開。
[[1]]
[1] "The" "birch" "canoe" "slid" "on" "the" "smooth" "planks."

[[2]]
[1] "Glue" "the" "sheet" "to" "the" "dark"
[7] "blue" "background."

[[3]]
[1] "It's" "easy" "to" "tell" "the" "depth" "of" "a" "well."

# simplifyTRUE時(shí)返回矩陣
> sentences %>% head(3) %>% str_split(" ", simplify = TRUE)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] "The" "birch" "canoe" "slid" "on" "the" "smooth" "planks." ""
[2,] "Glue" "the" "sheet" "to" "the" "dark" "blue" "background." ""
[3,] "It's" "easy" "to" "tell" "the" "depth" "of" "a" "well."
  • 因?yàn)樽址蛄康拿總€分量會包含不同數(shù)量的片段,所以 str_split() 會返回一個列表。如果拆分的是長度為 1 的向量,那么只要簡單地提取列表的第一個元素即可,.[[1]]的功能類似于head(1)

> "a|b|c|d" %>%
+ str_split("\\|") %>%
+ .[[1]] #[[是取子集函數(shù)[的變體,只提取單個元素,并丟棄名稱
[1
] "a" "b" "c" "d"
  • 參數(shù)n:表示拆分的片段數(shù),默認(rèn)為Inf,即返回所有片段還可以設(shè)定拆分片段的最大數(shù)量:

> fields <- c("Name: Hadley: baf", "Country: NZ", "Age: 35")

# 拆分成2段,返回為矩陣
> fields %>% str_split(": ", n = 2, simplify = TRUE)
[,1] [,2]
[1,] "Name" "Hadley: baf"
[2,] "Country" "NZ"
[3,] "Age" "35"
  • 參數(shù)pattern:除了模式,你還可以用boundary()來匹配字符、單詞、行和句子的邊界,以這些邊界來拆分字符串。

> x <- "This is a sentence. This is another sentence."
> str_split(x, " ")[[1]]
[1] "This" "is" "a" "sentence." "This" "is" "another" "sentence."
> str_split(x, boundary("word"))[[1]]
[1] "This" "is" "a" "sentence" "This" "is" "another" "sentence"

# boundary("word")的拆分效果比" "更靈活,前者結(jié)果中只有單詞,
后者結(jié)果中還有.

4.6 定位匹配內(nèi)容:str_locate()

  • 功能:定位模式在字符串中的位置??梢苑祷孛總€匹配的開始位置和結(jié)束位置。

  • 用法:

  • str_locate(string, pattern)

  • str_locate_all(string, pattern)

> fruit <- c("apple", "banana", "pear", "pineapple")
> str_locate(fruit, "a")
start end
[1,] 1 1
[2,] 2 2
[3,] 3 3
[4,] 5 5

5. 其他類型的模式

以下3個函數(shù)是同一類型函數(shù),都使用修飾函數(shù)控制匹配行為

5.1 regex() 函數(shù)

  • 當(dāng)使用一個字符串作為模式時(shí), R 會自動調(diào)用 regex() 函數(shù)對其進(jìn)行包裝。

# 正常調(diào)用:當(dāng)所有參數(shù)都為默認(rèn)設(shè)置時(shí),簡寫為僅字符串(模式)
> str_view(fruit, "nana")
# 上面形式是以下形式的簡寫:當(dāng)需要修改默認(rèn)參數(shù)時(shí),就需要寫出regex()函數(shù)
> str_view(fruit, regex("nana"))
  • 用法:regex(pattern, ignore_case = FALSE, multiline = FALSE, comments = FALSE, dotall = FALSE, ...)

  • 參數(shù):后面這幾個參數(shù)的默認(rèn)設(shè)置都是FALSE,也就是說,當(dāng)它們都是FALSE時(shí)即為我們前面所學(xué),regex()也可以簡寫為僅字符串(模式),只是前面學(xué)習(xí)時(shí)未寫出默認(rèn)參數(shù)而已,換言之,如果這些參數(shù)為TRUE,那就是不同的意思,可以通過修改參數(shù)來控制具體的匹配方式

  • ignore_case(忽略字母大小寫):默認(rèn)為FALSE,匹配時(shí)字母區(qū)分有大小寫。當(dāng) ignore_case = TRUE 時(shí),忽略字母大小寫,既可以匹配大寫字母,也可以匹配小寫字母,它總是使用當(dāng)前的區(qū) 域設(shè)置:

> bananas <- c("banana", "Banana", "BANANA")
# 默認(rèn)區(qū)分大小寫,只能匹配到第1個字符串
> str_view(bananas, "banana")
# 不區(qū)分大小寫,3個字符串都能匹配到
> str_view(bananas, regex("banana", ignore_case = TRUE))
  • multiline(多行):默認(rèn)為FALSE,即沒有多行的說法, ^ 和 $ 從完整字符串的開頭和末尾開始匹配。當(dāng) multiline = TRUE 時(shí),可使 ^ 和 $ 從每行的開頭和末尾開始匹配:

> x <- "Line 1\nLine 2\nLine 3"
# 默認(rèn)只能從完整字符串的開頭開始匹配,即只能匹配到第1Line
> str_extract_all(x, "^Line")[[1]]
[1] "Line"
# ^可以從每行的開頭開始匹配,即3Line都能匹配到
> str_extract_all(x, regex("^Line", multiline = TRUE))[[1]]
[1] "Line" "Line" "Line"
  • comments(注釋):如果為TRUE,可以在復(fù)雜的正則表達(dá)式中加入注釋和空白字符,以便更易理解。匹配時(shí)會忽略空格和 # 后面的內(nèi)容。如果想要匹配一個空格,你需要對其進(jìn)行轉(zhuǎn)義:"\\ ":

phone <- regex("
\\(? # 可選的開括號
(\\d{3}) # 地區(qū)編碼
[)- ]? # 可選的閉括號、短劃線或空格
(\\d{3}) # 另外3個數(shù)字
[ -]? # 可選的空格或短劃線
(\\d{3}) # 另外3個數(shù)字
"
, comments = TRUE)

> str_match("514-791-8141", phone)
[,1] [,2] [,3] [,4]
[1,] "514-791-814" "514" "791" "814"
  • dotall:為 TRUE 時(shí) . 可以匹配包括 \n(換行符) 在內(nèi)的所有字符

5.2 fixed() 函數(shù)

  • 功能:可以按照字符串的字節(jié)形式進(jìn)行精確匹配,它會忽略正則表達(dá)式中的所有特殊字符,并在非常低的層次上進(jìn)行操作。這樣可以不用進(jìn)行那些復(fù)雜的轉(zhuǎn)義操作,而且速度比普通正則表達(dá)式要快很多。

  • 用法:fixed(pattern, ignore_case = FALSE)

microbenchmark::microbenchmark(
fixed = str_detect(sentences, fixed("the")), # 用fixed() 函數(shù)精確匹配
regex = str_detect(sentences, "the"), # 用regex()函數(shù)匹配
times = 20
)

# 可見,用fixed()函數(shù)匹配到的結(jié)果要比regex()函數(shù)匹配到的少
#> Unit: microseconds
#> expr min lq mean median uq max neval cld
#> fixed 116 117 136 120 125 389 20 a
#> regex 333 337 346 338 342 467 20 b
  • 在匹配非英語數(shù)據(jù)時(shí),要慎用 fixed() 函數(shù)。它可能會出現(xiàn)問題,因?yàn)榇藭r(shí)同一個字符經(jīng)常有多種表達(dá)方式。如,定義 á 的方式有兩種:一種是單個字母 a,另一種是 a 加 上重音符號:

> a1 <- "\u00e1"
> a2 <- "a\u0301"
> c(a1, a2) #可見 a1 和 a2 表示的是同一字符
[1] "á" "a"
> a1 == a2 #但比較得到的結(jié)果是FALSE
[1] FALSE

# 這兩個字母的意義相同,但因?yàn)槎x方式不同,所以 fixed() 函數(shù)找不到匹配。
> str_detect(a1, fixed(a2))
[1] FALSE

5.3 coll() 函數(shù)

  • 功能:使用標(biāo)準(zhǔn)排序規(guī)則來比較字符串,這在進(jìn)行不區(qū)分大小寫的匹配時(shí)是非常有效的。

  • 用法:coll(pattern, ignore_case = FALSE, locale = "en", ...)

  • 參數(shù):可以通過設(shè)置 locale 參數(shù)(區(qū)域設(shè)置,默認(rèn)"en"(英語)),以確定使用哪種規(guī)則來比較字符。

> i <- c("I", "?", "i", "?")
> str_subset(i, coll("i", ignore_case = TRUE)) #不區(qū)分大小寫,默認(rèn)用英語匹配,i匹配到的是Ii
[1] "I" "i"
> str_subset(i, coll("i", ignore_case = TRUE, locale = "tr")) #不區(qū)分大小寫,區(qū)域設(shè)置用土耳其語匹配,i匹配到的是?和i
[1] "?" "i"
  • fixed() 和 regex() 函數(shù)中都有 ignore_case 參數(shù),但都無法選擇區(qū)域設(shè)置,而coll()函數(shù)可以選擇區(qū)域設(shè)置

  • coll()函數(shù)的弱點(diǎn)是速度,因?yàn)榇_定哪些是相同字符的規(guī)則比較復(fù)雜,與 regex() 和 fixed() 函數(shù)相比, coll() 確實(shí)比較慢。

5.4 boundary() 函數(shù)

  • 功能:匹配(字母、行、句子和單詞)邊界

  • 用法:boundary(type = c("character", "line_break", "sentence", "word"), skip_word_none = NA, ...)

  • 參數(shù):

  • type:要檢測的邊界類型,可以選c("character", "line_break", "sentence", "word"),即字母、行、句子和單詞,前面例子中用到的是匹配單詞邊界。

> x <- "This is a sentence."
> str_extract_all(x, boundary("word"))
[[1]]
[1] "This" "is" "a" "sentence"

練習(xí)

(1) 如何找出包含 \ 的所有字符串?分別使用 regex() fixed() 函數(shù)來完成這個任務(wù)。
> str_subset(c("a\\b", "ab"), "\\\\")
[1] "a\\b"
> str_subset(c("a\\b", "ab"), fixed("\\")) #盡管fixed()函數(shù)可以忽略正則表達(dá)式中的所有特殊字符,但書寫字符串使還是應(yīng)該注意特殊字符的特殊含義,比如\表示轉(zhuǎn)義。
[1] "a\\b"
> writeLines("a\\b")
a\b

(2) sentences 數(shù)據(jù)集中最常見的 5 個單詞是什么?

tibble(word = unlist(str_extract_all(sentences, boundary("word")))) %>% # 以單詞為邊界提取出句子中的所有單詞
mutate(word = str_to_lower(word)) %>% # 將單詞中的大寫轉(zhuǎn)化為小寫
count(word, sort = TRUE) %>% # 以單詞分組進(jìn)行計(jì)數(shù),并倒序排
head(5) # 選出前5個

# A tibble: 5 x 2
word n
<chr> <int>
1 the 751
2 a 202
3 of 132
4 to 123
5 and 118

6. 正則表達(dá)式的其他應(yīng)用

R 基礎(chǔ)包中有兩個常用函數(shù),它們也可以使用正則表達(dá)式。 

6.1 apropos() 函數(shù)

  • 功能:通過(部分)名稱查找對象,可以在全局環(huán)境空間中搜索所有可用對象。當(dāng)不能確切想起函數(shù)名稱時(shí),這個函數(shù)特別有用:

  • 用法:

> apropos("replace")
[1] "%+replace%" ".rs.registerReplaceHook" ".rs.replaceBinding"
[4] ".rs.rpc.replace_comment_header" "replace" "replace_na"
[7] "replacements" "setReplaceMethod" "str_replace"
[10] "str_replace_all" "str_replace_na"
"theme_replace"

6.2 dir() 函數(shù)

  • 功能:可以列出一個目錄下的所有文件

  • 用法:

  • dir() 函數(shù)的 patten 參數(shù)可以是一個正則表達(dá)式,此時(shí)它只返回與這個模式相匹配的文件名。

# 返回當(dāng)前目錄中的所有CSV文件
> head(dir(pattern = "\\.csv$"))
[1] "diamonds.csv"

7. stirngi

  • stringr 建立于 stringi 的基礎(chǔ)之上。

  • stringr 非常容易學(xué)習(xí),因?yàn)樗惶峁┝朔浅I俚暮瘮?shù)(只有42個)

  • 與 stringr 不同, stringi 的設(shè)計(jì)思想是盡量全面,幾乎包含了我們可以用到的所有函數(shù)(有 234 個函數(shù))。

  • 練習(xí)

(1) 找出可以完成以下操作的 stringi 函數(shù)。

a. 計(jì)算單詞的數(shù)量。 #stri_count_words()函數(shù)
> stri_count_words(head(sentences))
[1] 8 8 9 9 7 7

b. 找出重復(fù)字符串。 #stri_duplicated()函數(shù)
> stri_duplicated(c("the", "brown", "cow", "jumped", "over", "the", "lazy", "fox"))
[1] FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE

c. 生成隨機(jī)文本。
> stri_rand_strings(4, 5) #stri_rand_strings()生成隨機(jī)字符串
[1] "BabVd" "ozkiF" "PtBxp" "BRy6A"
> stri_rand_shuffle("The brown fox jumped over the lazy cow.") #stri_rand_shuffle()打亂順序
[1] "ojr mty.eTnowveo zo fbwe pulchhxed ar"


(2) 如何控制 stri_sort() 函數(shù)用來排序的語言設(shè)置?
# 通過區(qū)域設(shè)置
> string1 <- c("hladny", "chladny")
> stri_sort(string1, locale = "pl_PL")
[1] "chladny" "hladny"
> stri_sort(string1, locale = "sk_SK")
[1] "hladny" "chladny"
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
R語言字符串處理值stringr
《數(shù)據(jù)科學(xué)中的R語言》之字符串處理入門---比較全面
php中正則的使用
R語言stringr包的使用-2
[轉(zhuǎn)載]R語言字符串處理總結(jié)
NotePad++ 正則表達(dá)式替換 高級用法
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服