|
|
乖乖的骆驼 · 驻印度大使罗照辉会见奥里萨邦邦长扎米尔· 9 月前 · |
|
|
魁梧的眼镜 · 观点-教授/研究-长江商学院· 1 年前 · |
|
|
才高八斗的橙子 · 【纯爱推文】 | ...· 2 年前 · |
|
|
从容的金针菇 · 汽车之家|【QM&试车】新能源中的生力军—— ...· 2 年前 · |
|
|
呐喊的煎鸡蛋 · 《蜘蛛侠:英雄无归》影评:保持着良善的初衷, ...· 2 年前 · |
cppFunction()
转换简单的C++函数—Fibnacci例子
sourceCpp()
转换C++程序—正负交替迭代例子
sourceCpp()
转换C++源文件中的程序—正负交替迭代例子
sourceCpp()
转换C++源程序文件—卷积例子
wrap()
把C++变量返回到R中
as()
函数把R变量转换为C++类型
as()
和
wrap()
的隐含调用
clone
函数
kable()
函数制作表格
s <-
c("123", "abc", "张三李四", "@#$%^&")
## [1] "123" "abc" "张三李四" "@#$%^&"
R中处理文本型数据的函数有文件访问函数以及readLines,nchar,
paste,sprintf, format,formatC, substring等函数。
R支持正则表达式, 函数grep, grepl, sub, gsub, regexpr,
gregexpr, strsplit与正则表达式有关。
字符型函数一般都是向量化的,
对输入的一个字符型向量的每个元素操作。
R扩展包stringr和stringi提供了更方便、功能更强的字符串功能,
包括正则表达式功能。
其中stringr是常用功能,
stringi是更基本、更灵活的功能,
一般使用stringr就足够了。
stringr包的函数名大多都以str_开头。
下面先介绍常用的较简单的字符串函数,
包括stringr包的函数与基本R函数。
40.3 字符串连接、重复
stringr::str_c()用来把多个输入自变量按照元素对应组合为一个字符型向量,
用sep指定分隔符,默认为不分隔。
类似于R中向量间运算的一般规则,
各自变量长度不同时短的自动循环使用。
非字符串类型自动转换为字符型。
## [1] "x*a" "y*b"
## [1] "data1.txt" "data2.txt" "data3.txt"
字符型缺失值参与连接时,
结果变成缺失值;
可以用str_replace_na()函数将待连接的字符型向量中的缺失值转换成字符串"NA"再连接。
用collapse选项要求将连接后的字符型向量的所有元素连接在一起,
collapse的值为将多个元素合并时的分隔符。
## [1] "a---bc---def"
在使用了collapse时如果有多个要连接的部分,
str_c()函数先将各部分连接成为一个字符型向量,
然后再把结果的各个向量元素连接起来。
## [1] "data1.txt;data2.txt;data3.txt"
stringr::str_flatten()类似于stringr::str_c()仅有collapse参数作用一样,
仅将一个字符型向量的各个元素按照collapse参数指定的分隔符连接成一个长字符串,
collapse默认值是空字符串,如:
## [1] "a---bc---def"
## [1] "abcdef"
基本R的paste()函数与stringr::str_c()函数有类似的用法,
但是参数sep的默认值是空格。
基本R的paste0()函数相当于stringr::str_c()函数固定sep参数为空字符串。
## [1] "x*a" "y*b"
## [1] "data1.txt" "data2.txt" "data3.txt"
## [1] "data1.txt" "data2.txt" "data3.txt"
## [1] "a---bc---def"
## [1] "data1.txt;data2.txt;data3.txt"
stringr::str_dup(string, times)类似于rep()函数,
可以将字符型向量的元素按照times指定的次数在同一字符串内重复,如:
## [1] "abcabcabc" "长江长江长江"
也可以针对每个元素指定不同重复次数,如
## [1] "abcabcabc" "长江长江"
40.4 格式化输出
40.4.1 format()函数
format()函数可以将一个数值型向量的各个元素按照统一格式转换为字符型,
## [1] "1"
## [1] "1.2"
## [1] "1.23"
## [1] "1.00" "1.20" "1.23"
选项digits与nsmall共同控制输出的精度,
nsmall控制非科学记数法显示时小数点后的至少要有的位数,
digits控制至少要有的有效位数。
这使得输出的宽度是不可控的,
## [1] " 3.1415927" "31415.9265359"
width参数指定至少要有的输出宽度,
不足时默认在左侧用空格填充,如:
## [1] " 1.00"
format()还有许多选项,
详见函数的帮助。
40.4.2 sprintf()函数
format()函数无法精确控制输出长度和格式。
sprintf是C语言中sprintf的向量化版本,
可以把一个元素或一个向量的各个元素按照C语言输出格式转换为字符型向量。
第一个自变量是C语言格式的输出格式字符串,
其中%d表示输出整数,%f表示输出实数,
%02d表示输出宽度为2、不够左填0的整数,
%6.2f表示输出宽度为6、宽度不足时左填空格、含两位小数的实数,
比如,标量转换
## [1] " 3.14"
又如,向量转换:
## [1] "tour001.jpg" "tour005.jpg" "tour010.jpg" "tour015.jpg" "tour100.jpg"
还可以支持多个向量同时转换,如:
## [1] "1x5= 5" "2x4= 8" "3x3= 9" "4x2= 8" "5x1= 5"
40.4.3 字符串插值函数
许多脚本型程序设计语言都有在字符串的内容中插入变量值的功能,
R本身不具有这样的功能,
sprintf()函数有类似作用但只是一个不方便使用的副作用。
stringr::str_glue()和stringr::str_glue_data()提供了字符串插值的功能。
只要在字符串内用大括号写变量名,
则函数可以将字符串内容中的变量名替换成变量值,如:
## 姓名: 李明
## 电话号码: 13512345678
上面的例子直接用了换行符"\n"来分开不同内容。
也可以输入多个字符串作为自变量,
内容自动连接在一起,可以用参数.sep指定分隔符:
## 姓名: 李明, 电话号码: 13512345678
## 姓名: 李明; 电话号码: 13512345678
也可以直接在str_glue()中指定变量值,如:
## 姓名: 张三; 电话号码: 13588888888
stringr::str_glue_data()则以一个包含变量定义的对象.x为第一自变量,
类型可以是环境、列表、数据框等。如:
## 姓名: 王五; 电话号码: 13500000000
需要插入原样的大括号时,
可以双写,如:"{{...}}"。
40.5 字符串长度
stringr::str_length(string)求字符型向量string每个元素的长度。
一个汉字长度为1。
## [1] 1 2 3 2
函数nchar(text)计算字符串长度,默认按照字符个数计算而不是按字节数计算,
## [1] 1 2 3 2
注意函数对输入的字符型向量每个元素计算长度。
nchar()加选项type="bytes"可用按字符串占用的字节数计算,
这时一个汉字占用多个字节(具体占用多少与编码有关)。
## [1] 1 2 3 6
40.6 取子串
stringr::str_sub(string, start, end)字符串字串,
用开始字符位置start和结束字符位置end设定字串位置。
用负数表示倒数位置。
默认开始位置为1,
默认结束位置为最后一个字符。
## [1] "2017"
## [1] "2017" "2018"
## [1] "2017"
## [1] "2017"
## [1] "term"
取子串时,一般按照字符个数计算位置,如
## [1] "海淀区"
当起始位置超过总长度或结束位置超过第一个字符时返回空字符串;
当起始位置超过结束位置是返回空字符串。
## [1] ""
## [1] ""
## [1] ""
可以对str_sub()结果赋值,表示修改子串内容,如:
s <- "term2017"
str_sub(s, 5, 8) <- "18"
## [1] "term18"
字符串替换一般还是应该使用专用的替换函数如stringr::str_replace_all(),
gsub()。
基本R的substring(text, first, last)函数与stringr::str_sub()功能相同,
但first和last参数不允许用负数,
last的默认值是一个很大的数,所以省略last时会取到字符串末尾。
substring()对三个参数text, first, last都是向量化的,
长度不一致时按照一般的不等长向量间运算规则处理。如:
## [1] "term" "2018"
## [1] "term" "2017"
substring()也允许修改某个字符串的指定子串的内容,如
s <- "123456789"
substring(s, 3, 5) <- "abc"
## [1] "12abc6789"
R的substr(x, start, stop)作用类似,
但是仅支持x为字符型向量,
start和stop是标量。
40.7 字符串变换
40.7.1 大小写
stringr::str_to_upper(string)将字符型向量string中的英文字母都转换为大写。
类似函数有stringr::str_to_lower(string)转换为小写,
stringr::str_to_title(string)转换为标题需要的大小写,
stringr::str_to_scentence(string)转换为句子需要的大小写。
这都是针对英文的,
选项locale用来选语言,locale="en"为默认值。
基本R的toupper()将字符型向量的每个元素中的小写字母转换为大写,
tolower()转小写。
40.7.2 字符变换表
基本R的chartr(old, new, x)函数指定一个字符对应关系,
旧字符在old中,新字符在new中,x是一个要进行替换的字符型向量。
比如,下面的例子把所有!替换成.,把所有;替换成,:
## [1] "Hi, boy." "How do you do."
## [1] "昌平区,大兴区;固安区."
第二个例子中被替换的标点是中文标点,替换成了相应的英文标点。
40.7.3 空白处理
stringr::str_trim(string, side)返回删去字符型向量string每个元素的首尾空格的结果,
可以用side指定删除首尾空格("both")、开头空格("left")、末尾空格("right")。
## [1] "李明" "李明" "李明" "李 明"
## [1] "李明" "李明 " "李明 " "李 明"
## [1] " 李明" "李明" " 李明" "李 明"
stringr::str_squish(string)对字符型向量string每个元素,
删去首尾空格,将重复空格变成单个,返回变换后的结果。如:
## [1] "李明" "李明" "李明" "李 明"
基本R函数trimws(x, which)与str_trim()作用类似,
选项which="left"可以仅删去开头的空格,
选项which="right"可以仅删去结尾的空格。
## [1] "李明" "李明" "李明" "李 明"
## [1] "李明" "李明 " "李明 " "李 明"
## [1] " 李明" "李明" " 李明" "李 明"
为了去掉输入字符串中所有空格,可以用gsub()替换功能,如:
## [1] "李明" "李明" "李明" "李明"
stringr::str_pad(string, width)可以将字符型向量string的每个元素加长到width个字符,
不足时左补空格,已经达到或超过width的则不变,如:
## [1] " 12" "1234"
可以用选项side选择在哪里填补空格,
默认为"left",
还可选"right","both"。
40.7.4 截短或分行
stringr::str_trunc(x, width)可以截短字符串。
stringr::str_wrap(x, width)可以将作为字符型向量的长字符串拆分成近似等长的行,
行之间用换行符分隔。
40.7.5 排序
基本R函数sort()可以用来对字符型向量的各个元素按照字典序排序,
但是字符的先后顺序是按照操作系统的当前编码值次序,
见关于locales的帮助。
str_sort(x)对字符型向量x排序。
可以用locale选项指定所依据的locale,
不同的locale下次序不同。
默认为"en"即英语,
中国大陆的GB编码(包括GBK和GB18030)对应的locale是"zh"。
str_order(x)返回将x的各个元素从小到大排序的下标序列。
40.8 简单匹配与查找
40.8.1 开头和结尾匹配
基本R的startsWith(x, prefix)可以判断字符型向量x的每个元素是否以prefix开头,
结果为一个与x长度相同的逻辑型向量。如
## [1] FALSE TRUE
endsWith(x, suffix)可以判断字符型向量x的每个元素是否以suffix结尾,
## [1] TRUE FALSE
stringr包的str_starts(string, pattern)判断string的每个元素是否以模式pattern开头,
加选项negate=TRUE表示输出反面结果。
pattern是正则表达式,
如果需要用非正则表达式,可以用fixed()或者coll()保护,如:
## [1] FALSE TRUE
## [1] FALSE TRUE
stringr包的str_ends(string, pattern)判断是否以给定模式结尾。
40.8.2 中间匹配
函数grep(), grepl()等可以用于查找子字符串,
位置不限于开头和结尾,
详见§41.1。
在grepl()函数中加fixed=TRUE选项表示查找一般文本内容(非正则表达式)。
比如,查找字符串中是否含有our:
## [1] FALSE TRUE
40.9 字符串替换
stringr包的str_replace_all(string, fixed(pattern), replacement)在字符型向量string的每个元素中查找子串pattern,
并将所有匹配按照replacement进行替换。
## [1] "New **me" "Old times" "In ** present **me"
用gsub(pattern, replacement, x, fixed=TRUE)
把字符型向量x中每个元素中出现的子串
pattern都替换为replacement(注意与str_replace_all的自变量次序区别)。
## [1] "New **me" "Old times" "In ** present **me"
设有些应用程序的输入要求使用逗号“,”分隔,
但是用户可能输入了中文逗号“,”,
就可以用gsub()来替换:
## [1] "15.34,14.11" "13.25,16.92"
例子中x的第二个元素中的逗号是中文逗号。
函数sub()与gsub()类似,但是仅替换第一次出现的pattern。
40.10 字符串拆分
stringr::str_split(string, pattern)对字符型向量string的每一个元素按分隔符pattern进行拆分,
每个元素拆分为一个字符型向量,结果是一个列表,列表元素为字符型向量。
其中pattern是正则表达式,
为了按照固定模式拆分,用fixed()进行保护。如
x <- c("11,12", "21,22,23", "31,32,33,34")
res1 <- str_split(x, fixed(","))
## [[1]]
## [1] "11" "12"
## [[2]]
## [1] "21" "22" "23"
## [[3]]
## [1] "31" "32" "33" "34"
str_split()可以用选项n指定仅拆分出成几项,最后一项合并不拆分,如:
x <- c("11,12", "21,22,23", "31,32,33,34")
res2 <- str_split(x, fixed(","), n=2)
## [[1]]
## [1] "11" "12"
## [[2]]
## [1] "21" "22,23"
## [[3]]
## [1] "31" "32,33,34"
拆分的结果可以用lapply(), sapply(),vapply()等函数处理。
将每个元素的拆分结果转换成数值型:
## [[1]]
## [1] 11 12
## [[2]]
## [1] 21 22 23
## [[3]]
## [1] 31 32 33 34
可以用unlist()函数将列表中的各个向量连接成一个长向量,如:
## [1] "11" "12" "21" "22" "23" "31" "32" "33" "34"
注意,即使输入只有一个字符串,str_split()的结果也是列表,
所以输入只有一个字符串时我们应该取出结果列表的第一个元素,如
## [1] "31" "32" "33" "34"
如果确知每个字符串拆分出来的字符串个数都相同,
可以用stringr::str_split_fixed(),
用参数n指定拆出来的项数,
这时结果为一个字符型矩阵,
原来的每个元素变成结果中的一行:
x <- c("11,12", "21,22", "31,32")
res3 <- str_split_fixed(x, fixed(","), n=2)
## [,1] [,2]
## [1,] "11" "12"
## [2,] "21" "22"
## [3,] "31" "32"
基本R的strsplit(x,split,fixed=TRUE)
可以把字符型向量x的每一个元素按分隔符split拆分为一个字符型向量,
strsplit的结果为一个列表,
每个列表元素对应于x的每个元素。
x <- c("11,12", "21,22,23", "31,32,33,34")
res4 <- strsplit(x, split=",", fixed=TRUE)
## [[1]]
## [1] "11" "12"
## [[2]]
## [1] "21" "22" "23"
## [[3]]
## [1] "31" "32" "33" "34"
40.11 文本文件读写
文本文件是内容为普通文字、用换行分隔成多行的文件,
与二进制文件有区别,
二进制文件中换行符没有特殊含义,
而且二进制文件的内容往往也不是文字内容。
二进制文件的代表有图片、声音,
以及各种专用软件的的私有格式文件,
如Word文件、Excel文件。
对于文本文件,可以用readLines()函数将其各行的内容读入为一个字符型数组,
字符型数组的每一个元素对应于文件中的一行,
读入的字符型数组元素不包含分隔行用的换行符。
最简单的用法是读入一个本地的文本文件,
一次性读入所有内容,用如
其中filename.ext是文件名,
也可以用全路径名或相对路径名。
当文本文件很大的时候,
整体读入有时存不下,
即使能存下处理速度也很慢,
可以一次读入部分行,逐批读入并且逐批处理,这样程序效率更高。
这样的程序要复杂一些,例如
infcon <- file("filename.ext", open="rt")
batch <- 1000
repeat{
lines <- readLines(infcon, n=batch)
if(length(lines)==0) break
## 处理读入的这些行
close(infcon)
以上程序先打开一个文件,inffcon是打开的文件的读写入口(称为一个“连接对象”)。
每次读入指定的行并处理读入的行,直到读入了0行为止,
最后关闭infcon连接。
对文本文件的典型处理是读入后作一些修改,
另外保存。
函数writeLines(lines, con="outfilename.txt")可以将字符型向量lines的各个元素变成输出文件的各行保存起来,
自动添加分隔行的换行符。
如果是分批读入分批处理的,
则写入也需要分批写入,
以上的分批处理程序变成:
infcon <- file("filename.ext", open="rt")
outfcon <- file("outfilename.txt", open="wt")
batch <- 1000
while(TRUE){
lines <- readLines(infcon, n=batch)
if(length(lines)==0) break
## 处理读入的这些行, 变换成outlines
writeLines(outlines, con=outfcon)
close(outfcon)
close(infcon)
readLines()也可以直接读取网站的网页文件,
lines <- readLines(url("https://www.r-project.org/"))
length(lines)
## [1] 116
head(lines)
## [1] "<!DOCTYPE html>"
## [2] "<html lang=\"en\">"
## [3] " <head>"
## [4] " <meta charset=\"utf-8\">"
## [5] " <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">"
## [6] " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"
readr包的read_lines()和write_lines()函数起到与基本R中
readLines()和writeLines()类似的作用,
read_file()和read_file_raw()可以将整个文件读入为一个字符串。