往期回顾:
数据科学01 | 数据科学家的工具箱
➢安装R和Rstudio
➢设置工作目录
查看工作目录:
getwd()[1] "/Users/UserName"
更改工作目录:
setwd("~/Documents") dir() #查看当前目录文件
➢在R的文本编辑器编写代码
・通常使用文本文件/文本编辑器・缩进代码
仅靠缩进就能理解程序是按何种顺序运行的。
・限制代码的宽度
缩进可能会使代码无限制向右排,需要限制代码的宽度,一般将文本的列数限制在大约80列。
・限制函数的长度
有利于函数的易读性和调试。
在R中,对象(object)是指可以赋值给变量的任何事物,包括常量、数据结构、函数,甚至图形。
➢基本数据类型
・字符型character ・数值型numeric ・整数型integer ・逻辑型logic ・复数型complex
➢数据结构
・向量vector
存储数值型、字符型或逻辑型数据的一维数组。
・矩阵matrix
二维数组,每个元素都拥有相同的类型(数值型、字符型或逻辑型)。
・数组array
与矩阵类似,但是维度可以大于2。
・数据框dataframe
用来存储表格数据,每一列数据都可以是不同的类型。
・列表list
可以是几个向量、矩阵、数据框,甚至其他列表的集合。
・因子factor
类别变量和有序类别变量,可以分类数据。
1.if, else,测试逻辑条件
if(){ ##do something} else { ##do something else} if(){ ##do something} else if(){ ##do something different} else { ##do something different}#else 不是必需if(){ ##do something}if(){ ##do something}
2.for,执行固定次数的循环
x "a", for (i in 1:4) { print(x[i])}[1] "a"[1] "b"[1] "c"[1] "d"for (i in seq_along(x)) { #seq_along函数创建一个与向量等长的整数数列 print(x[i])}[1] "a"[1] "b"[1] "c"[1] "d"for (letter in x) { print(letter)}[1] "a"[1] "b"[1] "c"[1] "d"for (i in 1:4) print(x[i])[1] "a"[1] "b"[1] "c"[1] "d"
输出结果都一样。
x 1:for(i in seq_len(nrow(x))) { for(j in seq_len(ncol(x))) { print(x[i, j]) } }[1] 1[1] 3[1] 5[1] 2[1] 4[1] 6
for可以嵌套,但一般少于3层,否则不易解释。
3.while,条件成立时执行循环
count 0 while(count < 5) { print(count) count count + }[1] 0[1] 1[1] 2[1] 3[1] 4
4.repeat,执行无限循环
x01 tol 8repeat { x1 if(abs(x1 - x0) < tol) { break }else{ x0 } }
repeat循环易陷入死循环,需要注意!(在数据处理中不常用)
5.break,终止并跳出repeat循环
6.next,跳过循环的当前迭代
for(i in 1:100) { if(i <= 20) { ##跳过前20次迭代 next } ## Do something}
7.return,退出并返回值
R语言用 function() 创建函数。
f function() { ## Do something}
在R里函数可以作为对象处理,可以将函数作为参数传递给其它函数,也可以嵌套。
・形式参数是函数定义包含的参数。・缺省值:参数的默认值,调用函数并不需要指定每个参数的值。
➢参数匹配规则
函数参数可以根据位置或者名字来匹配——编写和调用函数的关键。
例:函数sd() ,可以计算数据的标准差
formals(sd) $x$na.rm[1] FALSE
formals()函数返回函数所有形式参数组成的列表。
sd() 读入名为 x 的向量
参数na.rm判断是否移除缺失值NA,na.rm缺省值是FALSE,即默认缺失值不参与计算
mydata 100)sd(mydata) #没有对参数进行了命名,默认将 mydata 作为第一个参数传递给函数[1] 0.9131906sd(x = mydata) #对参数进行了命名[1] 0.9131906sd(x = mydata, na.rm = FALSE) #命名所有参数[1] 0.9131906sd(na.rm = FALSE, x = mydata) #给变量命名的时候,不需要将它们按照特定顺序排列[1] 0.9131906sd(na.rm = FALSE, mydata) #只命名了第一个参数,命名的参数会按照命名来设定它们的值[1] 0.9131906#可以认为已命名的参数被移出了参数列表,然后其它参数值按照排列的先后顺序与函数参数匹配
不推荐改变参数的排列顺序,容易引起误解。
对参数极多的函数混合使用位置匹配和命名。
例:lm()函数,把数据拟合到线性模型
args(lm) function (formula, data, subset, weights, na.action, method = "qr", model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE, contrasts = NULL, offset, ...) NULL
args()可以查看函数的所有参数及其对应的缺省值。
前五个参数没有缺省值,使用者必须指定它们的值
参数 method、model 和 x 都有缺省值
比较两个等价的函数调用方式:
#方式一:lm(data = mydata, y ~ x, model = FALSE, 1:100)#方式二:lm(y ~ x, mydata, 1:100, model = FALSE)
方式一:
将data参数按照命名来匹配,移出参数列表
y ~ x 因为没有特定的名字,将赋值给第一个尚未配对的参数,即formula
model 参数按命名匹配,移出参数列表
1:100 将会被赋值给下一个未匹配的参数subset
用这种方式调用 lm() 会让人觉得混乱。通常使用方式二调用lm()。
R中的参数匹配顺序:
首先检查完全匹配,指定一个参数名,它会检查是否有参数跟该命名完全匹配
如果找不到完全匹配的参数,它将查找是否有模糊匹配的参数
如果都没有,则再进行位置匹配
➢惰性求值 (Lazy Evaluation)仅在函数参数被调用时进行求值。
f function(a, b) { a^2} #函数定义两个参数a和b,但只使用了一个参数af(2)[1] 4f function(a, b) { print(a) print(b) }f(45)[1] 45Error in print(b) : 缺少参数"b",也没有缺省值#没有给b赋值,参数b也没有缺省值,错误是在输出45之后出现的
➢特殊参数:...参数可以将原函数的一些参数迅速传递给另一个函数。
例:定义myplot()函数,拓展plot()函数
myplot function(x, y, plot(x, y, type = type, ...)}
1.重复使用原 plot() 函数使用的参数,比如 x 和 y;2.type参数的缺省值可以修改;3.plot() 函数的其它参数可以用 ... 来传递,不需要在扩展函数中重新输入或者创建。
泛型函数 (generic function):函数自身不做任何运算,根据数据类型使用合适的方法,这种类型函数的设置常常要用到...参数,使得附加参数可以传递给方法。
例:paste() 函数paste() 函数将一组字符串连起来生成新的字符向量,无法预先注明有多少参数需要连接。
args(paste)function (..., sep = " ", collapse = NULL)
1. ...参数 ,各种字符向量对象;2. sep参数,缺省值为空格,用分隔符连接字符;3. sep参数和collapse参数在 ... 参数之后。
任何出现在 ... 之后的参数列表需要明确地给出名称,而且不能进行模糊匹配!
paste("a", "b", sep = ":")[1] "a:b"paste("a", "b", se = ":")[1] "a b :"
paste() 函数中模糊匹配无效,R 并不知道需要将信息传递给 ... 参数,还是其他参数。
R 用了一种特殊的数据类型来表示日期和时间。
日期用 Date 类表示
时间由POSIXct类和POSIXlt类表示
日期不包括时间,只表示某年某月某日,日期以距离1970年1月1日的天数来存储数据
时间以距离1970年1月1日的秒数存储数据
as.Date() 函数将字符串格式的日期转换成Date类型。
x as.Date(x[1] "1970-01-01" #x不是character类,是Date类unclass(x) #去除对象x的类[1] 0 #日期以距1970年1月1日的天数来存储的,而1970年1月1日与x表示的日期相差0天unclass(as.Date("1970-01-02"))[1] 1 unclass(as.Date("1969-12-31"))[1] -1
POSIX 规定了特定类型的计算机处理事件和数据表示的方法。POSIX 标准里有一个标准族来规定如何表示日期和时间。
POSIXct 类的时间用非常大的整数表示,常作为数据框储存的时间数据的类。
POSIXlt类实际上把时间当作列表来存储
Sys.time() 函数返回系统当前的时间。
x x[1] "2020-01-10 01:33:02 CST"#以年月日的格式输出,紧接着是时分秒的格式,接着是时区class(x)[1] "POSIXct" "POSIXt" #时间为POSIXct类unclass(x)[1] 1578591183#对POSIXct类的对象x去除类,得到了非常大的整数,是自1970年1月1日至今的秒数
as.POSIXlt() 或 as.POSIXct() 函数可以在 POSIXlt 类和 POSIXct 类之间转换。
x x[1] "2020-01-10 01:20:26 CST"p names(unclass(p))[1] "sec" "min" "hour" "mday" "mon" "year" "wday" "yday" "isdst" [10]"zone" "gmtoff"#POSIXlt实际上是一个列表,去除类之后查看元素名p$sec #查看元素[1] 26.97712
strptime() 函数可以把字符串格式的日期转换成日期或时间对象。
datestring "January 10, 2012 10:40", x "%B %d, %Y %H:%M")x[1] "2012-01-10 10:40:00 CST" "2011-12-09 09:10:00 CST"class(x)[1] "POSIXlt" "POSIXt"
对日期或时间类的数据进行运算可以很方便。不能把不同的类混淆在一起计算。
x "2012-01-01")y "9 Jan 2011 11:34:21", x-yError in x - y : 二进列运算符中有非数值参数此外: Warning message:不可兼容的方法("-.Date", "-.POSIXt")和"-" x x)x-yTime difference of 356.3 days
日期和时间能计算不易理清的时间,例如闰年、闰秒、夏令时以及时区。
x as.Date(y as.Date(x-yTime difference of 2 days#2012年是闰年,两个日期相差2天x as.POSIXct(y as.POSIXct(y-xTime difference of 13 hours#时区不同,实际相差13小时
对日期和时间都通用的泛型函数:
・weekdays() 函数:给定的日期或时间是星期几 ・months() 函数:给定的日期或时间是在几月 ・quarters() 函数:给定的日期或时间处于第几季度
编辑:李雪纯 冯文清 校审:张健 罗鹏