R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大。
R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,互联网….都在使用R语言。
要成为有理想的极客,我们不能停留在语法上,要掌握牢固的数学,概率,统计知识,同时还要有创新精神,把R语言发挥到各个领域。让我们一起动起来吧,开始R的极客理想。
转载请注明出处:
http://blog.fens.me/r-stringr/
用R语言处理字符串,总觉得很麻烦,即不能用向量的方法进行分割,也不能用循环遍历索引。grep()家族函数常常记不住,paste()函数默认以空格分割,各种不顺手啊!随着使用R语言的场景越来越多,字符串处理是必不可少的。给大家推荐一个由 Hadley Wickham 开发的一个灵活的字符串处理包stringr。
stringr包被定义为一致的、简单易用的字符串工具集。所有的函数和参数定义都具有一致性,比如,用相同的方法进行NA处理和0长度的向量处理。
字符串处理虽然不是R语言中最主要的功能,却也是必不可少的,数据清洗、可视化等的操作都会用到。对于R语言本身的base包提供的字符串基础函数,随着时间的积累,已经变得很多地方不一致,不规范的命名,不标准的参数定义,很难看一眼就上手使用。字符串处理在其他语言中都是非常方便的事情,R语言在这方面确实落后了。stringr包就是为了解决这个问题,让字符串处理变得简单易用,提供友好的字符串操作接口。
stringr的项目主页: https://cran.r-project.org/web/packages/stringr/index.html
本文所使用的系统环境
stringr是在CRAN发布的标准库,安装起来非常简单,2条命令就可以了。
~ R > install.packages('stringr') > library(stringr)
stringr包1.0.0版本,一共提供了30个函数,方便我们对字符串处理。常用的字符串的处理以str_开头来命名,方便更直观理解函数的定义。我们可以根据使用习惯对函数进行分类:
参数控制函数,仅用于构造功能的参数,不能独立使用。
函数定义:
str_c(..., sep = "", collapse = NULL) str_join(..., sep = "", collapse = NULL)
参数列表:
把多个字符串拼接为一个大的字符串。
> str_c('a','b') [1] "ab" > str_c('a','b',sep='-') [1] "a-b" > str_c(c('a','a1'),c('b','b1'),sep='-') [1] "a-b" "a1-b1"
把多个向量参数拼接为一个大的字符串。
> str_c(head(letters), collapse = "") [1] "abcdef" > str_c(head(letters), collapse = ", ") [1] "a, b, c, d, e, f" # collapse参数,对多个字符串无效 > str_c('a','b',collapse = "-") [1] "ab" > str_c(c('a','a1'),c('b','b1'),collapse='-') [1] "ab-a1b1"
拼接有NA值的字符串向量时,NA还是NA
> str_c(c("a", NA, "b"), "-d") [1] "a-d" NA "b-d"
对比str_c()函数和paste()函数之间的不同点。
# 多字符串拼接,默认的sep参数行为不一致 > str_c('a','b') [1] "ab" > paste('a','b') [1] "a b" # 向量拼接字符串,collapse参数的行为一致 > str_c(head(letters), collapse = "") [1] "abcdef" > paste(head(letters), collapse = "") [1] "abcdef" #拼接有NA值的字符串向量,对NA的处理行为不一致 > str_c(c("a", NA, "b"), "-d") [1] "a-d" NA "b-d" > paste(c("a", NA, "b"), "-d") [1] "a -d" "NA -d" "b -d"
函数定义:
str_trim(string, side = c("both", "left", "right"))
参数列表:
去掉字符串的空格和TAB(/t)
#只过滤左边的空格 > str_trim(" left space/t/n",side='left') [1] "left space/t/n" #只过滤右边的空格 > str_trim(" left space/t/n",side='right') [1] " left space" #过滤两边的空格 > str_trim(" left space/t/n",side='both') [1] "left space" #过滤两边的空格 > str_trim("/nno space/n/t") [1] "no space"
函数定义:
str_pad(string, width, side = c("left", "right", "both"), pad = " ")
参数列表:
补充字符串的长度。
# 从左边补充空格,直到字符串长度为20 > str_pad("conan", 20, "left") [1] " conan" # 从右边补充空格,直到字符串长度为20 > str_pad("conan", 20, "right") [1] "conan " # 从左右两边各补充空格,直到字符串长度为20 > str_pad("conan", 20, "both") [1] " conan " # 从左右两边各补充x字符,直到字符串长度为20 > str_pad("conan", 20, "both",'x') [1] "xxxxxxxconanxxxxxxxx"
函数定义:
str_dup(string, times)
参数列表:
复制一个字符串向量。
> val <- c("abca4", 123, "cba2") # 复制2次 > str_dup(val, 2) [1] "abca4abca4" "123123" "cba2cba2" # 按位置复制 > str_dup(val, 1:3) [1] "abca4" "123123" "cba2cba2cba2"
函数定义:
str_wrap(string, width = 80, indent = 0, exdent = 0)
参数列表:
txt<-'R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,互联网….都在使用R语言。' # 设置宽度为40个字符 > cat(str_wrap(txt, width = 40), "/n") R语言作为统计学一门语言,一直在小众领域 闪耀着光芒。直到大数据的爆发,R语言变成 了一门炙手可热的数据分析的利器。随着越来 越多的工程背景的人的加入,R语言的社区在 迅速扩大成长。现在已不仅仅是统计领域,教 育,银行,电商,互联网….都在使用R语言。 # 设置宽度为60字符,首行缩进2字符 > cat(str_wrap(txt, width = 60, indent = 2), "/n") R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数 据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来 越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已 不仅仅是统计领域,教育,银行,电商,互联网….都在使用R语言。 # 设置宽度为10字符,非首行缩进4字符 > cat(str_wrap(txt, width = 10, exdent = 4), "/n") R语言作为 统计学一 门语言, 一直在小 众领域闪 耀着光芒。 直到大数据 的爆发,R 语言变成了 一门炙手可 热的数据分 析的利器。 随着越来 越多的工程 背景的人的 加入,R语 言的社区在 迅速扩大成 长。现在已 不仅仅是统 计领域,教 育,银行, 电商,互联 网….都在使 用R语言。
函数定义:
str_sub(string, start = 1L, end = -1L)
参数列表:
截取字符串。
> txt <- "I am Conan." # 截取1-4的索引位置的字符串 > str_sub(txt, 1, 4) [1] "I am" # 截取1-6的索引位置的字符串 > str_sub(txt, end=6) [1] "I am C" # 截取6到结束的索引位置的字符串 > str_sub(txt, 6) [1] "Conan." # 分2段截取字符串 > str_sub(txt, c(1, 4), c(6, 8)) [1] "I am C" "m Con" # 通过负坐标截取字符串 > str_sub(txt, -3) [1] "an." > str_sub(txt, end = -3) [1] "I am Cona"
对截取的字符串进行赋值。
> x <- "AAABBBCCC" # 在字符串的1的位置赋值为1 > str_sub(x, 1, 1) <- 1; x [1] "1AABBBCCC" # 在字符串从2到-2的位置赋值为2345 > str_sub(x, 2, -2) <- "2345"; x [1] "12345C"
函数定义:
str_count(string, pattern = "")
参数列表:
对字符串中匹配的字符计数
> str_count('aaa444sssddd', "a") [1] 3
对字符串向量中匹配的字符计数
> fruit <- c("apple", "banana", "pear", "pineapple") > str_count(fruit, "a") [1] 1 3 1 1 > str_count(fruit, "p") [1] 2 0 1 3
对字符串中的'.'字符计数,由于.是正则表达式的匹配符,直接判断计数的结果是不对的。
> str_count(c("a.", ".", ".a.",NA), ".") [1] 2 1 3 NA # 用fixed匹配字符 > str_count(c("a.", ".", ".a.",NA), fixed(".")) [1] 1 1 2 NA # 用//匹配字符 > str_count(c("a.", ".", ".a.",NA), "//.") [1] 1 1 2 NA
函数定义:
str_length(string)
参数列表:
计算字符串的长度:
> str_length(c("I", "am", "张丹", NA)) [1] 1 2 2 NA
函数定义:
str_sort(x, decreasing = FALSE, na_last = TRUE, locale = "", ...) str_order(x, decreasing = FALSE, na_last = TRUE, locale = "", ...)
参数列表:
对字符串值进行排序。
# 按ASCII字母排序 > str_sort(c('a',1,2,'11'), locale = "en") [1] "1" "11" "2" "a" # 倒序排序 > str_sort(letters,decreasing=TRUE) [1] "z" "y" "x" "w" "v" "u" "t" "s" "r" "q" "p" "o" "n" "m" "l" "k" "j" "i" "h" [20] "g" "f" "e" "d" "c" "b" "a" # 按拼音排序 > str_sort(c('你','好','粉','丝','日','志'),locale = "zh") [1] "粉" "好" "你" "日" "丝" "志"
对NA值的排序处理
#把NA放最后面 > str_sort(c(NA,'1',NA),na_last=TRUE) [1] "1" NA NA #把NA放最前面 > str_sort(c(NA,'1',NA),na_last=FALSE) [1] NA NA "1" #去掉NA值 > str_sort(c(NA,'1',NA),na_last=NA) [1] "1"
函数定义:
str_split(string, pattern, n = Inf) str_split_fixed(string, pattern, n)
参数列表:
对字符串进行分割。
> val <- "abc,123,234,iuuu" # 以,进行分割 > s1<-str_split(val, ",");s1 [[1]] [1] "abc" "123" "234" "iuuu" # 以,进行分割,保留2块 > s2<-str_split(val, ",",2);s2 [[1]] [1] "abc" "123,234,iuuu" # 查看str_split()函数操作的结果类型list > class(s1) [1] "list" # 用str_split_fixed()函数分割,结果类型是matrix > s3<-str_split_fixed(val, ",",2);s3 [,1] [,2] [1,] "abc" "123,234,iuuu" > class(s3) [1] "matrix"
函数定义:
str_subset(string, pattern)
参数列表:
> val <- c("abc", 123, "cba") # 全文匹配 > str_subset(val, "a") [1] "abc" "cba" # 开头匹配 > str_subset(val, "^a") [1] "abc" # 结尾匹配 > str_subset(val, "a$") [1] "cba"
函数定义:
word(string, start = 1L, end = start, sep = fixed(" "))
参数列表:
> val <- c("I am Conan.", "http://fens.me, ok") # 默认以空格分割,取第一个位置的字符串 > word(val, 1) [1] "I" "http://fens.me," > word(val, -1) [1] "Conan." "ok" > word(val, 2, -1) [1] "am Conan." "ok" # 以,分割,取第一个位置的字符串 > val<-'111,222,333,444' > word(val, 1, sep = fixed(',')) [1] "111" > word(val, 3, sep = fixed(',')) [1] "333"
函数定义:
str_detect(string, pattern)
参数列表:
> val <- c("abca4", 123, "cba2") # 检查字符串向量,是否包括a > str_detect(val, "a") [1] TRUE FALSE TRUE # 检查字符串向量,是否以a为开头 > str_detect(val, "^a") [1] TRUE FALSE FALSE # 检查字符串向量,是否以a为结尾 > str_detect(val, "a$") [1] FALSE FALSE FALSE
函数定义:
str_match(string, pattern) str_match_all(string, pattern)
参数列表:
从字符串中提取匹配组
> val <- c("abc", 123, "cba") # 匹配字符a,并返回对应的字符 > str_match(val, "a") [,1] [1,] "a" [2,] NA [3,] "a" # 匹配字符0-9,限1个,并返回对应的字符 > str_match(val, "[0-9]") [,1] [1,] NA [2,] "1" [3,] NA # 匹配字符0-9,不限数量,并返回对应的字符 > str_match(val, "[0-9]*") [,1] [1,] "" [2,] "123" [3,] ""
从字符串中提取匹配组,以字符串matrix格式返回
> str_match_all(val, "a") [[1]] [,1] [1,] "a" [[2]] [,1] [[3]] [,1] [1,] "a" > str_match_all(val, "[0-9]") [[1]] [,1] [[2]] [,1] [1,] "1" [2,] "2" [3,] "3" [[3]] [,1]
函数定义:
str_replace(string, pattern, replacement)
参数列表:
> val <- c("abc", 123, "cba") # 把目标字符串第一个出现的a或b,替换为- > str_replace(val, "[ab]", "-") [1] "-bc" "123" "c-a" # 把目标字符串所有出现的a或b,替换为- > str_replace_all(val, "[ab]", "-") [1] "--c" "123" "c--" # 把目标字符串所有出现的a,替换为被转义的字符 > str_replace_all(val, "[a]", "/1/1") [1] "/001/001bc" "123" "cb/001/001"
函数定义:
str_replace_na(string, replacement = "NA")
参数列表:
把NA替换为字符串
> str_replace_na(c(NA,'NA',"abc"),'x') [1] "x" "NA" "abc"
函数定义:
str_locate(string, pattern) str_locate_all(string, pattern)
参数列表:
> val <- c("abca", 123, "cba") # 匹配a在字符串中的位置 > str_locate(val, "a") start end [1,] 1 1 [2,] NA NA [3,] 3 3 # 用向量匹配 > str_locate(val, c("a", 12, "b")) start end [1,] 1 1 [2,] 1 2 [3,] 2 2 # 以字符串matrix格式返回 > str_locate_all(val, "a") [[1]] start end [1,] 1 1 [2,] 4 4 [[2]] start end [[3]] start end [1,] 3 3 # 匹配a或b字符,以字符串matrix格式返回 > str_locate_all(val, "[ab]") [[1]] start end [1,] 1 1 [2,] 2 2 [3,] 4 4 [[2]] start end [[3]] start end [1,] 2 2 [2,] 3 3
函数定义:
str_extract(string, pattern) str_extract_all(string, pattern, simplify = FALSE)
参数列表:
> val <- c("abca4", 123, "cba2") # 返回匹配的数字 > str_extract(val, "//d") [1] "4" "1" "2" # 返回匹配的字符 > str_extract(val, "[a-z]+") [1] "abca" NA "cba" > val <- c("abca4", 123, "cba2") > str_extract_all(val, "//d") [[1]] [1] "4" [[2]] [1] "1" "2" "3" [[3]] [1] "2" > str_extract_all(val, "[a-z]+") [[1]] [1] "abca" [[2]] character(0) [[3]] [1] "cba"
函数定义:
str_conv(string, encoding)
参数列表:
对中文进行转码处理。
# 把中文字符字节化 > x <- charToRaw('你好');x [1] c4 e3 ba c3 # 默认win系统字符集为GBK,GB2312为GBK字集,转码正常 > str_conv(x, "GBK") [1] "你好" > str_conv(x, "GB2312") [1] "你好" # 转UTF-8失败 > str_conv(x, "UTF-8") [1] "���" Warning messages: 1: In stri_conv(string, encoding, "UTF-8") : input data /xffffffc4 in current source encoding could not be converted to Unicode 2: In stri_conv(string, encoding, "UTF-8") : input data /xffffffe3/xffffffba in current source encoding could not be converted to Unicode 3: In stri_conv(string, encoding, "UTF-8") : input data /xffffffc3 in current source encoding could not be converted to Unicode
把unicode转UTF-8
> x1 <- "/u5317/u4eac" > str_conv(x1, "UTF-8") [1] "北京"
函数定义:
str_to_upper(string, locale = "") str_to_lower(string, locale = "") str_to_title(string, locale = "")
参数列表:
字符串大写转换:
> val <- "I am conan. Welcome to my blog! http://fens.me" # 全大写 > str_to_upper(val) [1] "I AM CONAN. WELCOME TO MY BLOG! HTTP://FENS.ME" # 全小写 > str_to_lower(val) [1] "i am conan. welcome to my blog! http://fens.me" # 首字母大写 > str_to_title(val) [1] "I Am Conan. Welcome To My Blog! Http://Fens.Me"
字符串在平常的数据处理中经常用过,需要对字符串进行分割、连接、转换等操作,本篇中通过介绍stringr,灵活的字符串处理库,可以有效地提高代码的编写效率。有了好的工具,在用R语言处理字符串就顺手了。