Basic Graphics

par()                           # 做一些全局设定
inipar <- par(no.randonly = T)  # save
par(inipar)                     # recovery
par(mfrow = c(2, 3))            # make a figure. 2 rows 3 cols
 
png('pic.png')

加,意味着自己无法成图,需要在前面有图的基础上绘制

# lines
lines(x = 1:6, y = 2:7, col = 'blue')  # 需要加线的点对
abline(a = 3, b = 2, col = 'green')    # b, k
abline(v = 0, h = 3)                   # 1
# text
text(x = 3, y = 2.5, label = 'y = 3')
  1. 斜率为 0 当然也能画,但是无穷就表示不了了。而且前者只能画一根,后者可以画好几根

plot

plot(x = -1:6,           # x 取值  
     y = 2*(-1:6),       # y 取值  
     type = 'o',         # 样式  
     family = 'serif',   # 文字衬线  
     xlim = c(-5, 7),    # x axim limits  
     ylim = c(-5,14),    # y axim  
     ylab = 'y----',     # y label  
     xlab = '----x',     # x label  
     main = 'plot e.g.'  # title  
)
 
plot(iris$Petal.Length)
plot(cos, 0, 2*pi)
plot(dnorm, -3, 3,  
     col = "#cc0000",  
     lwd = 5  
)
 
plot(mtcars$wt, mtcars$mpg,
	pch = 19,  # Solid circle
	cex = 1.5, # Make 150% size
	col = "#cc0000",
	main = "MPG as a Function of Weight of Cars",
	xlab = "Weight (in 1000 pounds)",
	ylab = "MPG")

不仅可以展示 dataset 中的信息,还可以画普通图像

它会根据内容自己给我们判断适合用什么样的图,包括最后的散点图

Histogram

hist(iris$Sepal.Length)
 
par(mfrow = c(3,1))  # 更改参数,让一页多图
# par = parameter
# c = concatenate
 
hist(iris$Petal.Width [iris$Species == "setosa"],
	xlim = c(0, 3),
	breaks = 9,
	main = "Petal Width for Setosa",
	xlab = "",
	col = "red")
# 这样仅仅只是来一遍,类似的来三遍,就能出三个了
par(mfrow = c(1, 1))  # 复原

Mosaic plot

ggplot2

Overlaying plot

hist(lynx,
     breaks = 14,          # "Suggests" 14 bins
     freq   = FALSE,       # Axis shows density, not freq.
     col    = "thistle1",  # Color for histogram
     main   = "Histogram of Annual Canadian LynxTrappings, 1821-1934",
     xlab   = "Number of Lynx Trapped")
# Add a normal distribution
curve(dnorm(x, mean = mean(lynx), sd = sd(lynx)),
     col = "thistle4",  # Color of curve
     lwd = 2,           # Line width of 2 pixels
     add = TRUE)        # Superimpose on previous graph
# Add two kernel density estimators
lines(density(lynx), col = "blue", lwd = 2)
lines(density(lynx, adjust = 3), col = "purple", lwd = 2)
# Add a rug plot
rug(lynx, lwd = 2, col = "gray")

Overlaying Plot 就是将两个图重叠,你要说为什么,应该就是让

summary(iris$Species)
describe()  # in 'psych' package

对当前内容的一点总结,后者比前者要详细一点

Example

set.seed(432)  
d0 <- data.frame(rs1 = sample(letters[1:4], 100, replace = T),  
                 rs2 = sample(LETTERS[21:22], 100, replace = T))  
  
barplot(1:5, names.arg = letters[1:5])  
barplot(table(d0$rs1), main = 'barplot')  # table 可以用计数  
  
boxplot(len ~ supp, data = ToothGrowth)   # table 可以用计数  
  
hist(rnorm(1000), breaks = 15)         # 分箱  
  
# hist with density  
d1 <- rnorm(1000)  
hist(d1, breaks = 100, freq = F, main = 'Histogram')  
lines(density(d1), col = 'blue', lwd = 2)  
# draw normal distribution  
d2 <- seq(min(d1), max(d1), len = 10000)  
lines(d2, dnorm(d2), col = 'red', lwd = 2)

Selecting Cases (Variables)

使用 [] 中加入判断语句来 select,单逻辑运算符

根据表现形式,可以猜到一个 var 后面一个 [] 应该会返回一个子表,那么可以利用新增变量来存储子表:i.setosa <- iris[iris$Species == "setosa", ]。⚠️ 注意这里 , 是必须的,为什么以后再说,说是什么只选了一行,没指定列,如果想要全部的列,就 blank 就好

没错,R 语言的变量命名与赋值有些不同:

  • 大小写敏感
  • 数字和符号不能开头 (有点不一样)
  • 可以用 . 来连接词 (很不一样)
  • 使用 <- 来赋值

Data Formats

n1 <- 15  # Default as double
n1        # 注意到 R 语言的解释,有些独特性,所以这句话直接返回值
typeof(n1)
l2 <- F   # logical

Vector 和 Matrix

Vector

基本运算

v1 <- c(1, 2, 3, 4, 5)  # 也可以是别的数据类型
is.vector(v1)  # TRUE
(v1 + c(1, 2))  # 1
rev(v1)
  1. 长度不匹配,会 warning,但是可以过,对应迭代加/乘

命名 & 添加

# name & append
x <- 1:3  
names(x) <- LETTERS[1:3]  # 注意到。names 返回的是一个向量对象
x['A']                      # 命名之后就像 map 一样可以索引了
append(x, runif(3), after = 2)

为向量元素赋值

# assign
z <- 1:5  
z[7] <- 8; z  
z <- NULL  
z[c(1, 3, 5)] <- 1:3; z
z[-c(1, 3)]  # 真的去掉不变 NA,会往前补

特殊方法

z <- c(1, 2, NA)  # 缺省
is.na(z)          # 逐个判断是否缺省
z[is.na(z)] <- 0  # 缺省置 0

向量排序

z <- sample(1:100, 10)  
order(z)     # 排序后下标  
z[order(z)]  # 按下标提取  
sort(z)      # 直接排序,与上一样

Matrix

# matrix
m1 <- matrix(c(T, T, F, F, T, F), nrow = 2)  # Default byrow = F
m2 <- matrix(c("a", "b",
			"c", "d"),
			nrow = 2, byrow = T)             # 1
m3 <- matrix(1:20, 4, 5)  # 4 rows 5 cols
 
x <- matrix(runif(20), 4, 5)  
nrow(x); ncol(x); dim(x)  # 行列数,dim 返回 4 5 向量  
x[c(2, 1), ]  # 第二行摆在新一  
x[, c(1, 3)]  
x[2, 1]  # located  
x[x[ , 1] < 0.5, 1]  # 第一列小于 .5 的  
x[-2, -c(1, 3)]  # 去掉第二行,第一列,第三列
 
x <- matrix(1:30, 5, 6)  
y <- matrix(rnorm(20), 4, 5)  
y %*% x  # 矩阵乘法  
apply(x, 1, mean)  # rows mean. sum, prod
 
x <- matrix(1:12, nrow = 3, 
			dimnames = list(c("I", "II", "III"),  # 用列表给矩阵行列名字
							paste("X", 1:4, sep = "-")))
x <- rnorm(10)  
all(x > 0); all(x != 0); any(x > 0)  # 都...吗,有...吗  
(1:10)[x > 0]  # 2
x <- sample(1:7, 5, rep = T)  
unique(x)  # 去重
  1. 这里 byrow = T 才是我直观的生成样子,但是默认是 F
  2. 所以说 R 语言没有理由啊,重载的东西太多了。x 中大于 0 的位置

Array

# array
# 1 through 24. rows cols tables
a1 <- array(1:24, c(4, 3, 2))  # 貌似没有 byrow 参数

Data Frame

一列一列为单位 (这也是为什么只有列可以指定因子,索引也只索引得出列)

也是多种数据,基本构建和 List 很像

# data frame
vNumeric <- c(1, 2, 3)
vCharacter <- c("a", "b", "c")
vLogical <- c(T, F, T)
 
dfa <- cbind(vNumeric, vCharacter, vLogical)  # 1
df <- as.data.frame(cbind(vNumeric, vCharacter, vLogical))  # 2
df2 <- cbind.data.frame(vNumeric, vCharacter, vLogical)  # 3
df$vNumeric  # 4
 
x <- matrix(1:6, 2, 3)
df3 <- as.data.frame(x)
attributes(df3)
names(df3) <- c("TOYOTA","GM","HUNDA")  # 这个有点奇怪
row.names(df3) <- c("2001","2002")      # 这个是真能改
 
attach(df3); detach(df3)  # using namespace
  1. 使用 cbind() 会让所有数据强制类型转换
  2. 意思是 cbind() 并不是会强制变咯?只是直接用会变?那么问题是发生在赋值过程的吗
  3. 我天,这两句话单独打印看看是一样的,但是用 $ 出来看是不一样的!感受上还是使用 cbind.data.frame() 好!
  4. $ 貌似是专门用在 data frame 中的

List

内容可以是不同的

# list
o1 <- c(1, 2, 3)
o2 <- c("a", "b", "c", "d")
o3 <- c(T, F, T, T, F)
 
list1 <- list(o1 = o1, o2, o3)  # 只有指定名称才能用 $ 和名称
 
list1$o1       # 深层索引
list1[['o1']]
list1[[1]]
 
list1['o1']    # 浅层列表索引
list1[1]
unlist(list1)  # 将列表变为向量,带名称 (没名字的就没名字)

Type Conversions

coerce3 <- as.integer(5)
coerce4 <- c("1", "2", "3")  # 虽然是三对引号,但是是 character
coerce5 <- as.numeric(c("1", "2", "3"))  # 成三个 double 了
 
coerce6 <- matrix(1:9, nrow = 3)
coerce7 <- as.data.frame(matrix(1:9, nrow = 3))
# 虽然看起来一样,但是是不同的数据类型

⚠️ 注意,在整个语句外面加一个括号会同时在终端打印 (因为被视作一个表达式)

Factor

可以在构建的时候指定为 factor,也可以给已存在的变量重新赋值为 factor

如果指定 factor,它总会是 integer,但是会显示它的 label

注意到,我用 $ 解引用的时候,并不是像 java 一样有“指针进去啦,外面改,里面也改”,R 语言里面不改,但是用同一个名字来解析。如果我真的是用临时变量,那就要用引号表示名字。$[[]] 好像是对等的

Entering Data

x <- c(1, 2, 3)  # 读作 get
assign("x", c(1, 2, 3))  # 名字纯以字符串的形式表示
  • :, go through. 两边闭区间!
  • ?, like man
seq()  # means sequences
seq(10)  # 1-10
seq(1, 10, .01)  # seq(30, 0, by = -3)
seq(-1, 10, len = 100)  # seq(-1, 10, length = 100)
seq(2, by = 3, length = 4)
  • c(), means concatenate (or combine or collect). c(1:4, 6:7), skip 5
  • scan(). twice enter to exit
rep()  # means repetition
rep(c(T, F), 5)  # 并不是二维
rep(c(T, F), each = 5)  # 是依次重复v
rep(3:5, 1:3)  # 3 4 4 5 5 5

Importing Data

推荐使用 rio package

View(rio_csv)

r_txt2 <- read.table("./mbb.txt", header = T, sep = "\t")
trends.csv <- read.csv("./mbb.csv", header = T)
rawdata <- read.table(file.choose(), header = T, sep = ",")

readxl

data1 <- read_excel(file.choose())
excel_sheets(file.choose())  # 返回工作簿中工作表的向量
 
# 批量读取
files <- list.files("./derectory/")
paths <- paste("./derectory/", files, sep = "")  # 1
  1. 字符串操作,这就是所谓的基于向量运算

Handling Data

dplyr

不太知道里头有些操作为什么要用这些,明明 data frame 也做得到啊。感觉就是还是图个方便,封装起来

library(dplyr)
t2 <- filter(ToothGrowth, nv %in% 1:50, nv2 == 'H')         # and 1
summarize(ToothGrowth, len_max = max(len))                  # 2
summarize(group_by(ToothGrowth, supp), len_max = max(len))  # 3
  1. [] 在 data frame 也是可以做到的,无非稍微繁琐一点,不过细节是,每一行的标号结果不一样
  2. 新一个新的 data frame,len_max 是自己指定名称
  3. group_by 对 ToothGrowth 按 supp 分组,然后向量运算。参数多的时候就是划分的加细
# pipe
# 简单来讲就是把左边的送给右边做第一个参数
# 适合函数嵌套的时候使用
# left_joint. 以第一个参数为基准,第二个参数中根据 by 找可以连接的
df1 %>% left_joint(df2, by = c('c2' == 'c3'))
# right_joint. 
# full_joint. 无基准,有的都有,有 by 的合并
# inner_joint. 无基准,没得都没

tidyr

列的分裂与合并

# 分裂
df4 <- df3 %>%
	separate(col = c5, sep = '-', into = c('c7', 'c8'), remove = F) %>%
	separate(col = c6, sep = '\\.', into = c('c9', 'c10'), remove = T)
# 合并
df4 <- df3 %>%
	unite(col = 'c11', c('c7', 'c8'), sep = '-', remove = F)  # 可能是新列所以字符串

长宽数据转换

# 宽数据 -> 长数据
df6 <- df5 %>%  # 1
	pivot_longer(cols = -c(1:2), names_to = 'varb', values_to = 'value')
# 长数据 -> 宽数据
df6 <- df5 %>%  # 2
	pivot_wider(names_from = c(area, varb), values_from = value)
  1. “长”我想意思就是把原本是列的东西变成值,所以一条数据会分裂成都个数据,数据量增加,变长
  2. names_from 可以来源于多个数据 (利用划分的加细),然后座位新的列因子,值再来源于一个就行了

Hierarchical Clustering

Principal Components

Less is More. That is, less noise and fewer unhelpful variables in data = more meaning.

aka Dimensionality Reduction

Principal Components Analysis (PCA):

  • Two variables.
  • Regression(回归)
  • Perpendicular distance
  • Collapse
  • Rotate

Went from 2D to 1D but maintained the most important information.

Regression

Out of many, one.


Function

oddcount <- function (v, s="Default") {  
  cnt <- 0  
  for(i in v) {  
    if(i %% 2 == 1) cnt <- cnt + 1  
  }  
  print(s)  
  (x <- 1)  
}
oddcount(1:10)

函数可以没有 return 此时最后一个值为返回值。⚠️ R 里要加上括号才算返回值

Syntax

ifelse()  # accelerate running speed