R语言笔记之字符串-日期-格式化代码

字符串常用函数

is.character():判断是否是字符串;
nchar():有几个字符;
length():变量的长度
如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
> x <- "Hello, World!";x
[1"Hello, World!"
> is.character(x)
[1TRUE
> length(x)
[11
> nchar(x)
[113
> x2 <- c("Hello","World!")
> length(x2)
[12
> nchar(x2)
[15 6

内置数据集

R中有两个内置数据集,分别为LETTERS和letters,分别为大写字母和小写字母,如下所示:

1
2
3
4
5
6
7
8
9
10
> letters
 [1"a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t"
[21"u" "v" "w" "x" "y" "z"
> LETTERS
 [1"A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T"
[21"U" "V" "W" "X" "Y" "Z"
> letters[2:5]
[1"b" "c" "d" "e"
> LETTERS[4:9]
[1"D" "E" "F" "G" "H" "I"

字符串的连接和分离

字符串的分离strsplit()

strsplit()函数用于分离字符串,如下所示:

1
2
3
4
5
6
7
8
pangram <- "The quick brown fox jumps over the lazy dog"
pangram
length(pangram)
str(pangram)
pangram_split <- strsplit(pangram, " ")
pangram_split
length(pangram_split[[1]])
str(pangram_split)

运行结果如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
> pangram <- "The quick brown fox jumps over the lazy dog"
> pangram
[1] "The quick brown fox jumps over the lazy dog"
> length(pangram)
[1] 1
> str(pangram)
chr "The quick brown fox jumps over the lazy dog"
> pangram_split <- strsplit(pangram, " ")
> pangram_split
[[1]]
[1] "The" "quick" "brown" "fox" "jumps" "over" "the" "lazy" "dog"
> length(pangram_split[[1]])
[1] 9
> str(pangram_split)
List of 1
$ : chr [1:9] "The" "quick" "brown" "fox" ...

字符串的连接paste()

字符串的连接用的是paste函数,如下所示:

1
2
> paste(c("hello","world"))
[1"hello" "world"

在为某些数据添加新的一列,进行分组时,很有用,如下所示:

1
2
3
> myvars<-paste("q",1:5,sep="") # 将q分别与1到5这五个数字连接起来
> myvars
[1] "q1" "q2" "q3" "q4" "q5"

字符串连接的注意事项

以字符串的分离结果为数据进行连接,结果如下所示:

1
2
> paste(result_split,collapse=" ")->x3;x3
[1"c(\"The\", \"quick\", \"brown\", \"fox\", \"jumps\", \"over\", \"the\", \"lazy\", \"dog\")"

会发现字符之间出现的斜杠,原理如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
List of 1
 $ : chr [1:9"The" "quick" "brown" "fox" ...
> result_split[[1]]
[1"The"   "quick" "brown" "fox"   "jumps" "over"  "the"   "lazy"  "dog"  
> paste(result_split[[1]],collapse = " ")
[1"The quick brown fox jumps over the lazy dog"
> str(result_split) 
List of 1
 $ : chr [1:9"The" "quick" "brown" "fox" ...
> paste(result_split[[1]],collapse = " ")
[1"The quick brown fox jumps over the lazy dog"
> paste(result_split[[1]],collapse = "*")
[1"The*quick*brown*fox*jumps*over*the*lazy*dog"

因为分离后的字符串结果为列表(list),对列表直接用paste进行连接时,容易出现这种情况,因此要对列表的第1个元素进行连接才能避免这种情况。另外,在进行连接时主,要用于collapase参数,即用什么连接,案例中使用了空格与星号进行连接。

同时调用sep和collapse进行连接

以下面的这个例子中,先使用sep对不同向量进行连接,然后用collapse进行连接。

1
2
> paste(LETTERS[1:5],1:5,sep="_",collapse = "---")
[1"A_1---B_2---C_3---D_4---E_5"

paste创建有规律的变量名

创造含有sample1-5的五个元素的向量:

1
2
> paste("Sample",1:5)
[1"Sample 1" "Sample 2" "Sample 3" "Sample 4" "Sample 5"

字符的排序

排序用sort(),如果要倒序,则添加decreasing = TRUE,如下所示:

1
2
3
4
5
6
7
8
> sort(letters)
 [1"a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t"
[21"u" "v" "w" "x" "y" "z"
> sort(letters,decreasing = TRUE)
 [1"z" "y" "x" "w" "v" "u" "t" "s" "r" "q" "p" "o" "n" "m" "l" "k" "j" "i" "h" "g"
[21"f" "e" "d" "c" "b" "a"
> sort(result_split[[1]])
[1"brown" "dog"   "fox"   "jumps" "lazy"  "over"  "quick" "the"   "The"

查找文本

所用的案例是美国州的名字,数据集为state.name,如果要获取字符串的子字符串,则有2种方法,分别为:

  1. 通过位置:例如让R返回从第5个位置开始的紧接的第3个字母。
  2. 通过模式,例如返回匹配某个模式的子集。

通过位置查询

此函数为substr,现在返回state.name中各个元素的第3到第6的子字符串,如下所示:

1
2
3
4
> head(state.name)
[1"Alabama"    "Alaska"     "Arizona"    "Arkansas"   "California" "Colorado"  
> head(substr(state.name, start = 3,stop=6))
[1"abam" "aska" "izon" "kans" "lifo" "lora"

通过模式查找匹配字符串

grep()函数可提取子字符串,它需要2个参数:

  1. pattern:想要查询的模式;
  2. x:被查询的向量。

需要注意的是grep()函数区分大小写
现在查找名称中含有“New”的州,如下所示:

1
2
3
4
> grep("New",state.name)
[129 30 31 32
> grep("new",state.name)
integer(0)

返回的是数值变量,它表示的是元素的位置,例如:

1
2
3
4
> grep("New",state.name)
[129 30 31 32
> state.name[c(29,30)]
[1"New Hampshire" "New Jersey"

可以直接返回元素,如下所示:

1
2
> state.name[grep("New",state.name)]
[1"New Hampshire" "New Jersey"    "New Mexico"    "New York"

文本替换

sub()函数可以用于检索文本中的特定模式,并将其替换为其它的文本;
gsub()可以实现所有的替换功能,它的三个参数为:查找的字符串,替换的字符串与被修改的文本。
例如替换A real world is cute中的cute与ugly:

1
2
3
x1 <- "A real world is cute."
x1
gsub("cute","ugly",x1)

子字符串的提取案例之一:

一个向量,包含3个文件名,分别为file_a.csv,file_b.csv,file_c.csv,现在要提取这3个文件名中的a、b和c,需要用两个步骤,分别为:

  1. 将字符串“file_”替换为空格;
  2. 将“.csv”去掉,如下所示:
1
2
3
4
5
> x <- c("file_a.csv","file_b.csv","file_c.csv")
> y <- gsub("file_","",x);y
[1"a.csv" "b.csv" "c.csv"
> gsub(".csv","",y)
[1"a" "b" "c"

大小写转换toupper()与tolower()

所用到的函数是toupper()tolower(),如下所示:

1
2
3
4
5
6
7
8
9
> x <- c("word")
> toupper(x)
[1] "WORD"
> x <- c("word")
> y <- c("Excel")
> toupper(x)
[1] "WORD"
> tolower(y)
[1] "excel"

日期格式的创建

日期通常以字符串的形式输入到R中,然后转化为数值形式存储的日期变量,函数as.Date()用于执行这种转化,其语法为as.Date(x, "input_format"),其中x是
字符型数据,input_format则是读入日期的适当格式。

其格式如下所示:

1
2
3
4
5
6
7
8
%d 数字表示的日期(0~31) 例如01~31
%a 缩写的星期名 例如Mon
%A 非缩写的星期名 例如Monday
%m 月份(00~12) 例如00~12
%b 缩写的月份 例如Jan
%B 非缩写的月份 例如January
%y 两位数的年份 例如07
%Y 四位数的年份  例如2007

默认的日期格式为yyyy-mm-dd,语句为:

1
2
3
mydates <- as.Date(c("2007-06-22","2004-02-13"))
mydates
str(mydates)

结果如下:

mydates <- as.Date(c(“2007-06-22”,”2004-02-13”))
mydates
[1] “2007-06-22” “2004-02-13”
str(mydates)
Date[1:2], format: “2007-06-22” “2004-02-13”

weekdays()函数

返回某个日期是星期几如下所示:

1
2
3
4
5
6
7
8
9
## 格式转化
​```r
> strDates <- c("01/05/1965", "08/16/1975")
> dates <- as.Date(strDates, "%m/%d/%Y")
#输入的日期转化为对应日期,其中%m对应为月份,%d对应为日期,%Y对应为年
> dates
[1] "1965-01-05" "1975-08-16"
> str(dates)
 Date[1:2], format: "1965-01-05" "1975-08-16"

案例:

在leadership数据集中,日期是以mm/dd/yy的格式来表示的,现在将其转化为默认的yyyy-mm-dd格式,代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
> myformat <- "%m/%d/%y"
> leadership$testDate <- as.Date(leadership$testDate, myformat)
> leadership
  managerID   testDate country gender age item1 item2 item3 item4 item5 stringsAsFactor
1         1 2008-10-24      US      M  32     5     4     5     5     5           FALSE
2         2 2008-10-28      US      F  45     3     5     2     5     5           FALSE
3         3 2008-10-01      UK      F  25     3     5     5     5     2           FALSE
4         4 2008-10-12      UK      M  39     3     3     4    NA    NA           FALSE
5         5 2009-05-01      UK      F  NA     2     2     1     2     1           FALSE
  agecat
1  Young
2  Young
3  Young
4  Young
5   <NA>

当前日期

1
2
3
4
5
6
7
8
9
> Sys.Date() # 给出当前日期
[1"2014-01-18"
> date() #返回当前的日期和时间
[1"Sat Jan 18 14:22:07 2014"
> today<-Sys.Date()
> format(today,format = "%B %d %Y"# 格式化当前日期
[1"一月 18 2014"
> format(today,fomat ="%A")
[1"2014-01-18"

两个日期的相减

1
2
3
4
> startdate <- as.Date("2004-02-12")
> enddate <- as.Date("2011-01-22")
> days <-enddate - startdate;days # 两个时间点之差
Time difference of 2536 days

用difftime()来计算时间间隔,并以星期,天,时,分,秒来表示。

1
2
3
4
> today <- Sys.Date()
> dob <- as.Date("1956-10-12")
> difftime(today, dob, units="weeks")
Time difference of 2988.143 weeks

as.character(dates)用于将日期转化为字符型变量,其它与日期有关的函数可以查看help(as.Date),help(strftime),与日期有关的包为lubridate,复杂日期计算有关
的包为fCalendar。

格式化R代码format()与sprintf()

这一步通常是在计算了所有的数据之后进行的,主要用于输出一份报表,使输出的数据看起来比较整齐 ,例如我们可以设置小数点对齐,或指定固定的列宽,或者是添加一些货币符号,或百分号。

如果要实现上述功能,用到的函数就是format(),它可以将数字变成美观的文本需要注意的是,此时数字会转换为文本,也就是转换为字符串,因此这一步要在最后一步进行。format()的参数如下所示:

  • trim:逻辑值。FALSE表示通过添加空格现实现文本的右对齐;TRUE会去掉前面的空格;
  • digits:控制显示的有效数字的个数;
  • nsmall:小数点后最少显示多少个数字;
  • decimal.mark:小数点的格式;
  • big.mark:设置小数点前整数部分的分段符;
  • small.mark:设置小数点后小数部分的分段符。

案例1:fromat()输出小数

看一个案例,我们要输出一个数字12345.6789,以逗号作为小数点空格作为整数部分的分段符点号作为小数部分的分段符(分段则是3个数字作为一段),如下所示:

1
2
format(12345.6789, diits = 9, decimal.mark=",",
big.mark = " ", small.mark = ".", small.interval = 3)

运行结果如下所示:

1
2
3
> format(12345.6789, diits = 9, decimal.mark=",",
+ big.mark = " ", small.mark = ".", small.interval = 3)
[1] "12 345,68"

使用print()函数时,也可以使用digits参数,如下所示:

1
2
> print(11/3,digits=3)
[1] 3.67

案例2:format()输出列表

计算mtcars中某几列的平均值,并且以两位小数的形式将其输出,如下所示:

1
2
x <- colMeans(mtcars[,1:4])
format(x, digits = 2, nsamll = 2)

运行结果如下所示:

1
2
3
4
> x <- colMeans(mtcars[,1:4])
> format(x, digits = 2, nsamll = 2)
mpg cyl disp hp
" 20.1" " 6.2" "230.7" "146.7"

案例3:sprintf()添加百分号%

sprintf是一种能够使用输出的字符以C语言的风格进行格式化,sprintf的第一个参数包含字符串或数字变量的点位符,其他参数则将逐个代入这些占位符1

如下所示:

1
2
y <- seq(0.5, 0.55, 0.01)
sprintf("%.1f %%", 100*y)

运行结果如下所示:

1
2
> sprintf("%.1f %%", 100*y)
[1] "50.0 %" "51.0 %" "52.0 %" "53.0 %" "54.0 %" "55.0 %"

解释一下:"%.1f %%", 100*y是用来格式化字符串的,这在C与Python中很常见,这是告诉函数要将哪此部分远的为变量,%.1f表示将传入的第一个值进行格式化,要求显示小数点后一位数字 ,%%则是表示输出一个%

案例4:sprintf()输出货币格式

输出货币格式只需要在sprintf()函数中添加上一个$符号即可,如下所示:

1
2
3
set.seed(1000)
z <- 1000*runif(5)
sprintf("$ %3.2f", z)

运行结果如下所示:

1
2
3
4
> set.seed(1000)
> z <- 1000*runif(5)
> sprintf("$ %3.2f", z)
[1] "$ 327.88" "$ 758.85" "$ 113.94" "$ 690.76" "$ 516.40"

案例5:sprintf()替换变量

再看一个sprintf()函数的案例,这个在Python或C中会经常遇到:

1
2
3
stuff <- c("bread", "cookies")
price <- c(2.1, 4)
sprintf("%s costed $ %3.2f", stuff, price)

运行结果如下所示:

1
2
3
4
> stuff <- c("bread", "cookies")
> price <- c(2.1, 4)
> sprintf("%s costed $ %3.2f", stuff, price)
[1] "bread costed $ 2.10" "cookies costed $ 4.00"

formatC()使用C语言风格格式化数字

formatC可以使用C语言风格来输出字符串,可以指定使用固定型或科学型的格式,小数的位数以及输出的宽度,无论使用哪种选项,输入都应该是numeric类型(包括数组),输出的是character字符向量或数组,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
> pow <- 1:3
> formatC(pow)
[1] "1" "2" "3"
> powers_of_e <- exp(pow)
> powers_of_e
[1] 2.718282 7.389056 20.085537
> formatC(powers_of_e)
[1] "2.718" "7.389" "20.09"
> formatC(powers_of_e,digits=3)
[1] "2.72" "7.39" "20.1"
> formatC(powers_of_e,digits=3,width = 10)
[1] " 2.72" " 7.39" " 20.1"

特殊字符

有一些特殊字符可以被以包含在字符中,例如我们可以通过\t来插入一个制表符,下面我们使用cat()函数来输出这种特殊字符,这里不使用print()是因为print执行的额外转换动作会所制表符\t转换成反斜框和一个t.。cat的参数fill = TRUE使光标在一行结束后移动到下一行,如下所示1

1
2
> cat("foo\tbar", fill=TRUE)
foo bar

使用\n可以输出换行符,如下扬尘:

1
2
3
> cat("foo\nbar", fill = TRUE)
foo
bar

这里的转义字符与Python语言类似,不再多述。

文件路径

参考《数据的导入与导出》那篇笔记。

参考资料

  1. R语言轻松入门与提高 [法]Andrie de Vries ,[比利时]Joris Mey
1. 学习R.[美] Richard,Cotton 著刘军 译