R语言基础(1):常用方法

从Python到R

相比于Python,R语言在进行统计分析建模及可视化方面有明显优势,且很多算法提供了R版本但不一定有Python。而两种语言在数据处理分析等方面其实相像,因此可以通过类比熟悉一下R语言,以便快速上手R并完成一些工作。本文小结R语言基础,主要涉及

  1. 基本语法,数据类型
  2. 常用函数,流程控制(写循环)
  3. 文件读写及数据框的常规操作

目前我用Python最常用的有以下操作:

  1. 用列表或字典存数据;写for循环;创建DataFrame。
  2. 批量获取文件名;读写csv文件,获取表格字段信息等;行列筛选;分组聚合。
  3. 对DataFrame进行运算,apply函数应用。

R的基础语法和数据类型?在R中上述常规操作如何实现?

R基础

对象类型

R中的对象即是我们通常理解的变量

R的索引默认从1开始而非0

数值类型:TRUE/FLASE; integer; numric; complex; character; raw(二进制)

特殊:Inf(正无穷); -Inf; NaN(非数字); NA(缺失,不存在); NULL(空变量,元素存在但是没赋值)

  1. 向量/Vector,c(),相当于数组,其内元素的类型必须相同
  2. 列表/List,list(),类似于Python中的list但是包容性更强,可以同时包含多种不同类型的数据
  3. 矩阵/Matrix,matrix(),二维数组
  4. 数组/Array,array()
  5. 因子/Factor,factor(),类别变量
  6. 数据框/Data Frame,data.frame(),表格数据,每列为一个向量,列名为name

运算

  1. 比较:用==; !=来比较整数/向量/字符串是否相等,用all.equal(a,b)比较两个数字

  2. 变量赋值:<-; =,都可以 无区别,个人习惯=,全局变量赋值<<-

  3. 逻辑向量:& ! |,与非或,根据向量生成逻辑向量any();all()

循环/流程控制

  1. if else
1
2
3
4
5
if(x>3)
{
y=6
} else
{message("ok")}
  1. repeat循环,结合next; break
1
2
3
4
5
6
7
8
9
10
11
12
13
n=0;j=0
message("do while")
repeat{
n=n+1
if(n%%7==0)
{
message(n)
next #跳过后续代码直接进入下一次迭代
}
j=j+1
if(n==100) break #结束循环
}
# j=86,跳过了14次
  1. while循环,直接用
  2. for循环
1
2
for(i in 1:5){} 
for(n in c(TRUE, FALSE)){}

常用函数

查看信息

library(bfast): 导入三方包,此处为bfast

Rscript test.R:运行脚本

ls():查看所有变量,ls(pattern=“ab”)可以正则匹配

rm(list=ls()):删除所有变量

class(); mode(); typeof():查看变量/数值类型:

1
2
3
4
x = array(1:24, dim=c(4,3,2))
class(x) #"array"
mode(x) #"numeric"
typeof(x) #"integer"

length():计算向量长度

dim():返回多维向量的维度

names():对象命名, R中可以给每个对象赋予名称,类似于字典的

unlist();将多维list展开成一维

options(digits=n):设置全局小数点显示位数

summary():汇总函数,输出向量最大最小值四分位数等信息,也可以作用与data.frame,每列的汇总信息

attribute/查看对象的所有属性裂变

View()以电子表格的形式查看data.frame

文件路径相关

R中支持正斜杠/或双反斜杠\\

path = getwd():返回当前工作路径

file.path("c","program files","R"):拼接,类似于Python中的os.path.join()

files = dir(path ,pattern = "\\.csv$"):返回路径下所有csv文件名

filenames = dir(path ,pattern = "\\.csv$", full.names = TRUE):返回文件名绝对路径

basename(file):文件名

path.expand("~"):返回当前绝对"C:/Users/huangs/Documents"

创建”字典name”

1
2
3
x = c(1:4)
names(x) = c('a1','a2','a3','a4')
x['a1']

创建序列”range”

1:10:创建一个1~10的序列

seq(); seq.int():相当于Python中的range()

seq_alone(x):创建一个和x一样长的,从1开始的序列

1
2
3
4
5
seq(0, 1, length.out = 11) # 0.1~1.0
seq.int(0,10) #0 1 ... 10
seq(1, 9, by = 2) # 1 3 5 7 9
seq(1.575, 5.125, by = 0.05)
seq(17) #等价于seq.int(17) seq(1:17) seq_len(17)

rep(1:5),3:基于一个序列的重复构造新序列,有多个参数可选,可以自定义重复规则

runif(30,1, 50):服从标准/随机分布的30个数,random uniform seq

创建时间序列

有关R中的时间在另外的笔记中进行总结

seq.Date: Generate Regular Sequences of Dates。api

1
2
3
4
5
6
7
8
9
10
11
12
## first days of years
seq(as.Date("1910/1/1"), as.Date("1999/1/1"), "years")
## by month
seq(as.Date("2000/1/1"), by = "month", length.out = 12)
## quarters
seq(as.Date("2000/1/1"), as.Date("2003/1/1"), by = "quarter")

## find all 7th of the month between two dates, the last being a 7th.
st <- as.Date("1998-12-17")
en <- as.Date("2000-1-7")
ll <- seq(en, st, by = "-1 month")
rev(ll[ll > st & ll < en])

seq.POSIXt: Generate Regular Sequences of Times。api

1
2
3
4
5
6
7
8
9
10
11
## first days of years
seq(ISOdate(1910,1,1), ISOdate(1999,1,1), "years")
## by month
seq(ISOdate(2000,1,1), by = "month", length.out = 12)
seq(ISOdate(2000,1,31), by = "month", length.out = 4)
## quarters
seq(ISOdate(1990,1,1), ISOdate(2000,1,1), by = "quarter") # or "3 months"
## days vs DSTdays: use c() to lose the time zone.
seq(c(ISOdate(2000,3,20)), by = "day", length.out = 10)
seq(c(ISOdate(2000,3,20)), by = "DSTday", length.out = 10)
seq(c(ISOdate(2000,3,20)), by = "7 DSTdays", length.out = 4)

apply运算

  • lapply(list(),f(x))"list apply"
    • list中的每一个元素依次计算f(),并返回一个新的list
  • vapply(list()/vector(), f(x), numeric(1))"vaetor apply":返回vector,但需要确保结果可用vector包装并指定返回的数据类型及长度
  • eapply();遍历环境中的变量
  • mapply():多参数apply,
  • tapply:类似group bywith(data, tapply(x1, x2, f()))
    • by, aggregate
  • library(plyr):指定输入输出形式的apply函数
    • ddply(); 输入输出为data.frame
    • llply();输入输出均为list
    • laply();输入list,输出array

CSV读写

  • 数据加载:load(file = "...rda")

  • csv读写:

1
2
df = read.csv(path, header = TRUE,encoding = "UTF-8")
write.csv(df,file = '....csv',row.names = F)

异常捕获

trycatch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
tryCatch({
# 待执行/判断的代码
a+b
}, warning = function(w){
# 出现warning状态时执行,可以输出警告,也可以执行其它命令
print("warning")
}, error = function(e){
# 出现Error状态时执行,可以输出错误,也可以执行其它命令
print(error)
k = -1
print(k)
},finally = {
return(k)
# 这里的代码最后一定会执行
})

表格操作

R中的data.frame类似于Python的pandas dataframe ,用于表示表格型数据,应用十分灵活方便

行列选择

1
2
3
4
5
6
7
# 创建
data.frame(
x = c(..)
y = c(..)
z = c(..)
names = c('ID',...)
row.names = c(1,2,...))

其他操作

1
2
3
4
5
6
7
8
9
10
# 获取表格信息
str(df)
summary(df)
#转置
t(df)
colSums(df[,])/colMeans(df[,]) #计算列的和及均值
# 增加新列
df$new_col = c(..)
# 增加新行,拼接两个df
newdf = rbind(df1, df2)

新建csv并追加data.frame

1
2
3
4
5
6
7
8
9
10
11
12
13
14
outfile = "../.*csv"
out.table = data.frame()
for (colname in names(df)){
gridid = colname
x = df[,colname]
res = myfun(x)
k = res[1]
pvalue = res[2]
ktime = times[k]
# Populate the row
new.row = data.frame(gridid = gridid, ktime = ktime, pvalue = pvalue)
out.table = rbind(out.table, new.row)
}
write.csv(out.table,file = outfile, row.names = F)

拆分

groups = split(df, df$Quarter):返回的是dflist,通过索引访问,如groups[1]

拆分后遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
df <- data.frame(
Weekday = factor(rep(c("Mon", "Tues", "Wed", "Thurs", "Fri"), each = 4),
levels = c("Mon", "Tues", "Wed", "Thurs", "Fri")),
Quarter = paste0("Q", rep(1:4, each = 5)),
Delay = c(9.9, 5.4, 8.8, 6.9, 4.9, 9.7, 7.9, 5, 8.8, 11.1, 10.2, 9.3, 12.2,
10.2, 9.2, 9.7, 12.2, 8.1, 7.9, 5.6))

gs = split(df, df$Quarter)
for(gp in gs)
{
tempdf = data.frame(gp)
print(tempdf$Weekday)
}

dplyr包

一个功能强大的数据处理包dplyr

安装:install.packages("tidyverse");install.packages("dplyr")

%>%管道操作符,该符号的意思是将前者作为后者的输入参数进行传入

拆分group_split

Groupby分类汇总

参考1

操作实例

1
2
3
4
5
6
7
8
9
10
11
df <- data.frame(
Weekday = factor(rep(c("Mon", "Tues", "Wed", "Thurs", "Fri"), each = 4),
levels = c("Mon", "Tues", "Wed", "Thurs", "Fri")),
Quarter = paste0("Q", rep(1:4, each = 5)),
Delay = c(9.9, 5.4, 8.8, 6.9, 4.9, 9.7, 7.9, 5, 8.8, 11.1, 10.2, 9.3, 12.2,
10.2, 9.2, 9.7, 12.2, 8.1, 7.9, 5.6))

library(dplyr)
df %>%
group_by(Weekday) %>%
summarize(min_delay = min(Delay), max_delay = max(Delay))