R语言总结

文章发布时间:

最后更新时间:

文章总字数:
7.3k

预计阅读时间:
35 分钟

R语言是一种编程语言和环境,专门用于统计计算和图形绘制。它是“引擎”,负责执行所有计算任务。

为了有更好的编写R语言的体验,我们可以下载RStudio,它是一个**集成开发环境(IDE)**。它本身不执行计算,而是为 R 提供一个更好用、更强大的用户界面,包含代码编辑器、调试工具、图形显示窗口等,让你用 R 编程更加高效舒适。

首先先从安装R以及RStudio开始吧

安装R语言

访问 官网 The Comprehensive R Archive Network

根据你的操作系统选择下载安装程序,这里以windows为例

点击页首的 “Download R for Windows”

点击 “install R for the first time” (首次安装 R)。

点击页面顶部的 “Download R X.X.X for Windows” (X.X.X 是当前最新版本号)开始下载安装程序(一个 .exe 文件)。

双击下载好的 .exe 文件。

安装过程中基本一直点击 “下一步” 即可,所有默认设置对新手都很友好。

语言选择:可以选择中文,也可以使用英文。

安装位置:不建议更改,使用默认路径 C:\Program Files\R\

组件选择:保持全选默认状态。

启动选项:选择“No(接受自定义)”即可。

完成安装。

可以在系统变量路径中添加 bin 路径就可以全局使用 R 了

安装RStudio

安装完 R 之后,再来安装更好用的界面 RStudio。

访问 RStudio 官网

选择对应操作系统的安装程序,点击 “Download RStudio Desktop for windows”

双击下载的 .exe 文件,同样一路“下一步”即可,无需更改默认设置。

启动 RStudio,会自动匹配到你安装好的R,如果找不到,你也可以手动关联

之后就能在Console中编写代码来测试环境是否配置完成了

下载ISLR2数据集

建议您访问书籍的官方网站,上面有最权威的下载链接和安装指南

在网站上,你可以找到:

  1. 电子书下载(免费)。
  2. 实验手册(Labs)的R和Python代码。
  3. 数据集的直接下载链接(如果需要手动下载)。
  4. 以及其他更新信息。

你也可以编写R语言来通过命令下载ISLR2数据集:

选择File>New File>R Script新建一个文件,在其中编写代码如下:

1
2
3
install.packages("ISLR2")
library(ISLR2)
data()

选中代码,点击右上角的Run,运行成功后会显示R data sets,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
Data sets in package ‘datasets’:

AirPassengers Monthly Airline Passenger Numbers
1949-1960
BJsales Sales Data with Leading Indicator
BJsales.lead (BJsales)
Sales Data with Leading Indicator
BOD Biochemical Oxygen Demand
CO2 Carbon Dioxide Uptake in Grass Plants
ChickWeight Weight versus age of chicks on different
diets
DNase Elisa assay of DNase
EuStockMarkets Daily Closing Prices of Major European
Stock Indices, 1991-1998
Formaldehyde Determination of Formaldehyde
HairEyeColor Hair and Eye Color of Statistics Students
Harman23.cor Harman Example 2.3
Harman74.cor Harman Example 7.4
Indometh Pharmacokinetics of Indomethacin
InsectSprays Effectiveness of Insect Sprays
JohnsonJohnson Quarterly Earnings per Johnson & Johnson
Share
LakeHuron Level of Lake Huron 1875-1972
LifeCycleSavings Intercountry Life-Cycle Savings Data
Loblolly Growth of Loblolly Pine Trees
Nile Flow of the River Nile
Orange Growth of Orange Trees
OrchardSprays Potency of Orchard Sprays
PlantGrowth Results from an Experiment on Plant Growth
Puromycin Reaction Velocity of an Enzymatic Reaction
Seatbelts Road Casualties in Great Britain 1969-84
Theoph Pharmacokinetics of Theophylline
Titanic Survival of passengers on the Titanic
ToothGrowth The Effect of Vitamin C on Tooth Growth in
Guinea Pigs
UCBAdmissions Student Admissions at UC Berkeley
UKDriverDeaths Road Casualties in Great Britain 1969-84
UKgas UK Quarterly Gas Consumption
USAccDeaths Accidental Deaths in the US 1973-1978
USArrests Violent Crime Rates by US State
USJudgeRatings Lawyers' Ratings of State Judges in the US
Superior Court
USPersonalExpenditure
Personal Expenditure Data
UScitiesD Distances Between European Cities and
Between US Cities
VADeaths Death Rates in Virginia (1940)
WWWusage Internet Usage per Minute
WorldPhones The World's Telephones
ability.cov Ability and Intelligence Tests
airmiles Passenger Miles on Commercial US Airlines,
1937-1960
airquality New York Air Quality Measurements
anscombe Anscombe's Quartet of 'Identical' Simple
Linear Regressions
attenu The Joyner-Boore Attenuation Data
attitude The Chatterjee-Price Attitude Data
austres Quarterly Time Series of the Number of
Australian Residents
beaver1 (beavers) Body Temperature Series of Two Beavers
beaver2 (beavers) Body Temperature Series of Two Beavers
cars Speed and Stopping Distances of Cars
chickwts Chicken Weights by Feed Type
co2 Mauna Loa Atmospheric CO2 Concentration
crimtab Student's 3000 Criminals Data
discoveries Yearly Numbers of Important Discoveries
esoph Smoking, Alcohol and (O)esophageal Cancer
euro Conversion Rates of Euro Currencies
euro.cross (euro) Conversion Rates of Euro Currencies
eurodist Distances Between European Cities and
Between US Cities
faithful Old Faithful Geyser Data
fdeaths (UKLungDeaths)
Monthly Deaths from Lung Diseases in the
UK
freeny Freeny's Revenue Data
freeny.x (freeny) Freeny's Revenue Data
freeny.y (freeny) Freeny's Revenue Data
gait Hip and Knee Angle while Walking
infert Infertility after Spontaneous and Induced
Abortion
iris Edgar Anderson's Iris Data
iris3 Edgar Anderson's Iris Data
islands Areas of the World's Major Landmasses
ldeaths (UKLungDeaths)
Monthly Deaths from Lung Diseases in the
UK
lh Luteinizing Hormone in Blood Samples
longley Longley's Economic Regression Data
lynx Annual Canadian Lynx trappings 1821-1934
mdeaths (UKLungDeaths)
Monthly Deaths from Lung Diseases in the
UK
morley Michelson Speed of Light Data
mtcars Motor Trend Car Road Tests
nhtemp Average Yearly Temperatures in New Haven
nottem Average Monthly Temperatures at
Nottingham, 1920-1939
npk Classical N, P, K Factorial Experiment
occupationalStatus Occupational Status of Fathers and their
Sons
penguins Measurements of Penguins near Palmer
Station, Antarctica
penguins_raw (penguins)
Measurements of Penguins near Palmer
Station, Antarctica
precip Annual Precipitation in Selected US Cities
presidents Quarterly Approval Ratings of US
Presidents
pressure Vapor Pressure of Mercury as a Function of
Temperature
quakes Locations of Earthquakes off Fiji
randu Random Numbers from Congruential Generator
RANDU
rivers Lengths of Major North American Rivers
rock Measurements on Petroleum Rock Samples
sleep Student's Sleep Data
stack.loss (stackloss)
Brownlee's Stack Loss Plant Data
stack.x (stackloss)
Brownlee's Stack Loss Plant Data
stackloss Brownlee's Stack Loss Plant Data
state.abb (state) US State Facts and Figures
state.area (state) US State Facts and Figures
state.center (state)
US State Facts and Figures
state.division (state)
US State Facts and Figures
state.name (state) US State Facts and Figures
state.region (state)
US State Facts and Figures
state.x77 (state) US State Facts and Figures
sunspot.m2014 (sunspot.month)
Monthly Sunspot Data, from 1749 to
"Present"
sunspot.month Monthly Sunspot Data, from 1749 to
"Present"
sunspot.year Yearly Sunspot Data, 1700-1988
sunspots Monthly Sunspot Numbers, 1749-1983
swiss Swiss Fertility and Socioeconomic
Indicators (1888) Data
treering Yearly Tree-Ring Data, -6000-1979
trees Diameter, Height and Volume for Black
Cherry Trees
uspop Populations Recorded by the US Census
volcano Topographic Information on Auckland's
Maunga Whau Volcano
warpbreaks The Number of Breaks in Yarn during
Weaving
women Average Heights and Weights for American
Women

Data sets in package ‘ISLR2’:

Auto Auto Data Set
Bikeshare Bike sharing data
Boston Boston Data
BrainCancer Brain Cancer Data
Caravan The Insurance Company (TIC) Benchmark
Carseats Sales of Child Car Seats
College U.S. News and World Report's College Data
Credit Credit Card Balance Data
Default Credit Card Default Data
Fund Fund Manager Data
Hitters Baseball Data
Khan Khan Gene Data
NCI60 NCI 60 Data
NYSE New York Stock Exchange Data
OJ Orange Juice Data
Portfolio Portfolio Data
Publication Time-to-Publication Data
Smarket S&P Stock Market Data
Wage Mid-Atlantic Wage Data
Weekly Weekly S&P Stock Market Data


Use ‘data(package = .packages(all.available = TRUE))’
to list the data sets in all *available* packages.

这个列表中包含书中使用的所有经典数据集,如 Auto, Boston, Carseats, Credit, Wage 等。

R语言基础

现在让我们开始学习R语言的基础知识。R语言就像一个强大的计算器,但它能做的远不止简单运算。我们将从最基本的概念开始,逐步建立起对R语言的理解。

1. R作为计算器

打开RStudio,在Console窗口中,你可以直接输入数学表达式。R会立即计算并返回结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 基本算术运算
2 + 3 # 加法:返回 5
10 - 4 # 减法:返回 6
3 * 4 # 乘法:返回 12
15 / 3 # 除法:返回 5
2^3 # 幂运算:2的3次方,返回 8
17 %% 5 # 取余数:17除以5的余数,返回 2
17 %/% 5 # 整除:17除以5的商,返回 3

# 数学函数
sqrt(16) # 平方根:返回 4
abs(-5) # 绝对值:返回 5
exp(1) # e的1次方:返回 2.718282
log(10) # 自然对数:返回 2.302585
log10(100) # 以10为底的对数:返回 2

2. 变量和赋值

在R中,我们使用箭头 <- 或等号 = 来给变量赋值。箭头是R的传统写法,更受推荐,因为它清楚地表示了”将右边的值赋给左边的变量”这个方向性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 创建变量
x <- 5 # 将5赋值给变量x
y <- 10 # 将10赋值给变量y
result <- x + y # 将x和y的和赋值给result
print(result) # 显示result的值:15

# 变量命名规则
my_variable <- 100 # 使用下划线
myVariable <- 200 # 使用驼峰命名法
data.2024 <- 300 # 可以包含点和数字
# 2data <- 400 # 错误!不能以数字开头
# my-var <- 500 # 错误!不能使用连字符

# 查看和管理变量
ls() # 列出当前环境中的所有变量
rm(x) # 删除变量x
rm(list = ls()) # 清空所有变量(慎用)

3. 数据类型

R有几种基本的数据类型,理解它们是掌握R语言的关键。每种类型都有其特定用途。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 数值型(numeric)- 用于存储数字
age <- 25
height <- 175.5
class(age) # 查看类型:"numeric"

# 字符型(character)- 用于存储文本
name <- "张三"
city <- 'Beijing' # 单引号或双引号都可以
class(name) # 返回 "character"

# 逻辑型(logical)- 用于存储真/假值
is_student <- TRUE # 或写作 T
is_married <- FALSE # 或写作 F
class(is_student) # 返回 "logical"

# 类型转换
num_str <- "123" # 这是字符串
num_val <- as.numeric(num_str) # 转换为数值:123
str_val <- as.character(456) # 数值转字符串:"456"
bool_val <- as.logical(1) # 1转为TRUE,0转为FALSE

# 检查数据类型
is.numeric(age) # 返回 TRUE
is.character(name) # 返回 TRUE
is.logical(is_student) # 返回 TRUE

4. 向量(Vector)

向量是R中最基本的数据结构,可以理解为一组相同类型元素的有序集合。在R中,即使单个数值也被视为长度为1的向量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 创建向量
numbers <- c(1, 2, 3, 4, 5) # c()函数用于组合元素
fruits <- c("apple", "banana", "orange")
scores <- c(85, 92, 78, 95, 88)

# 创建序列
seq1 <- 1:10 # 创建1到10的整数序列
seq2 <- seq(0, 100, by=10) # 从0到100,步长为10
seq3 <- seq(0, 1, length.out=5) # 从0到1,等分为5个数

# 重复元素
rep1 <- rep(0, times=5) # 将0重复5次:0 0 0 0 0
rep2 <- rep(c(1,2), times=3) # 重复整个向量3次:1 2 1 2 1 2
rep3 <- rep(c(1,2), each=3) # 每个元素重复3次:1 1 1 2 2 2

# 向量运算(向量化运算是R的强大特性)
v1 <- c(1, 2, 3, 4)
v2 <- c(5, 6, 7, 8)
v1 + v2 # 对应元素相加:6 8 10 12
v1 * 2 # 每个元素乘以2:2 4 6 8
v1 > 2 # 返回逻辑向量:FALSE FALSE TRUE TRUE

# 访问向量元素
scores[1] # 第1个元素(R从1开始计数):85
scores[c(1, 3, 5)] # 第1、3、5个元素:85 78 88
scores[2:4] # 第2到第4个元素:92 78 95
scores[-2] # 除了第2个元素外的所有元素
scores[scores > 90] # 条件筛选:大于90的分数

# 向量的基本函数
length(scores) # 向量长度:5
sum(scores) # 求和:438
mean(scores) # 平均值:87.6
median(scores) # 中位数:88
sd(scores) # 标准差:6.580274
min(scores) # 最小值:78
max(scores) # 最大值:95

5. 矩阵(Matrix)

矩阵是二维的数据结构,所有元素必须是相同类型。在统计分析中,矩阵运算非常重要。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 创建矩阵
# 方法1:使用matrix函数
mat1 <- matrix(1:12, nrow=3, ncol=4) # 3行4列,按列填充
mat2 <- matrix(1:12, nrow=3, ncol=4, byrow=TRUE) # 按行填充

# 方法2:组合向量
vec1 <- c(1, 2, 3)
vec2 <- c(4, 5, 6)
mat3 <- cbind(vec1, vec2) # 按列组合
mat4 <- rbind(vec1, vec2) # 按行组合

# 矩阵属性
dim(mat1) # 维度:3 4
nrow(mat1) # 行数:3
ncol(mat1) # 列数:4

# 访问矩阵元素
mat1[2, 3] # 第2行第3列的元素
mat1[2, ] # 第2行的所有元素
mat1[, 3] # 第3列的所有元素
mat1[1:2, 2:3] # 第1-2行,第2-3列的子矩阵

# 矩阵运算
A <- matrix(c(1,2,3,4), nrow=2)
B <- matrix(c(5,6,7,8), nrow=2)
A + B # 元素对应相加
A * B # 元素对应相乘(不是矩阵乘法)
A %*% B # 矩阵乘法
t(A) # 转置
solve(A) # 求逆矩阵(如果存在)

6. 数据框(Data Frame)

数据框是R中最重要的数据结构之一,类似于Excel表格。它可以存储不同类型的数据,每列可以是不同的数据类型,但每列内的数据类型必须相同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 创建数据框
student_data <- data.frame(
name = c("Alice", "Bob", "Charlie", "David"),
age = c(20, 21, 19, 22),
score = c(85, 92, 78, 95),
passed = c(TRUE, TRUE, FALSE, TRUE)
)

# 查看数据框
print(student_data) # 显示整个数据框
head(student_data, 2) # 显示前2行
tail(student_data, 2) # 显示后2行
str(student_data) # 显示结构信息
summary(student_data) # 显示统计摘要

# 访问数据框
student_data$name # 访问name列(返回向量)
student_data[, "score"] # 另一种访问列的方式
student_data[2, ] # 第2行
student_data[2, 3] # 第2行第3列
student_data[1:2, c("name", "age")] # 前2行的name和age列

# 条件筛选
student_data[student_data$age > 20, ] # 年龄大于20的所有行
student_data[student_data$passed == TRUE, "name"] # 通过考试的学生姓名

# 添加新列
student_data$grade <- c("B", "A", "C", "A") # 添加成绩等级列
student_data$age_group <- ifelse(student_data$age >= 21, "Adult", "Young")

# 修改数据
student_data$score[3] <- 80 # 修改第3个学生的分数
student_data[student_data$name == "Bob", "age"] <- 22 # 修改Bob的年龄

7. 列表(List)

列表是R中最灵活的数据结构,可以包含任何类型的元素,包括向量、矩阵、数据框,甚至其他列表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 创建列表
my_list <- list(
numbers = c(1, 2, 3),
name = "R Programming",
matrix = matrix(1:4, nrow=2),
data = student_data
)

# 访问列表元素
my_list$numbers # 使用$符号
my_list[[1]] # 使用双方括号(返回元素本身)
my_list[1] # 使用单方括号(返回子列表)
my_list[["name"]] # 使用名称访问

# 添加或修改元素
my_list$new_element <- "New" # 添加新元素
my_list[[2]] <- "Updated Name" # 修改第2个元素

# 列表长度和名称
length(my_list) # 列表中元素的个数
names(my_list) # 元素的名称

控制结构

控制结构让我们能够控制代码的执行流程,这是编程的核心概念之一。

1. 条件语句

条件语句让程序可以根据不同的条件执行不同的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# if语句
score <- 85
if (score >= 90) {
print("优秀")
} else if (score >= 80) {
print("良好")
} else if (score >= 60) {
print("及格")
} else {
print("不及格")
}

# ifelse函数(向量化的条件判断)
scores <- c(85, 92, 78, 95, 58)
grades <- ifelse(scores >= 90, "A",
ifelse(scores >= 80, "B",
ifelse(scores >= 70, "C",
ifelse(scores >= 60, "D", "F"))))
print(grades) # "B" "A" "C" "A" "F"

# switch语句(多分支选择)
day <- 3
day_name <- switch(day,
"Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday", "Sunday"
)
print(day_name) # "Wednesday"

2. 循环结构

循环让我们可以重复执行某段代码,这在处理大量数据时特别有用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# for循环
# 示例1:遍历向量
fruits <- c("apple", "banana", "orange")
for (fruit in fruits) {
print(paste("I like", fruit)) # paste函数用于连接字符串
}

# 示例2:使用序列
total <- 0
for (i in 1:10) {
total <- total + i # 累加1到10
}
print(total) # 55

# 示例3:遍历数据框
for (i in 1:nrow(student_data)) {
cat("Student:", student_data$name[i],
"Score:", student_data$score[i], "\n")
}

# while循环
count <- 1
while (count <= 5) {
print(paste("Count is", count))
count <- count + 1 # 别忘了更新条件,避免无限循环
}

# repeat循环(需要使用break跳出)
x <- 1
repeat {
print(x)
x <- x + 1
if (x > 5) {
break # 当x大于5时跳出循环
}
}

# 循环控制语句
for (i in 1:10) {
if (i == 5) {
next # 跳过当前迭代,继续下一次
}
if (i == 8) {
break # 跳出整个循环
}
print(i)
} # 输出:1 2 3 4 6 7

函数

函数是组织代码的基本方式,让我们可以重复使用代码逻辑。R中有大量内置函数,我们也可以创建自己的函数。

1. 创建函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 基本函数定义
calculate_area <- function(radius) {
area <- pi * radius^2
return(area) # return可以省略,R会返回最后一个表达式的值
}

# 使用函数
circle_area <- calculate_area(5)
print(circle_area) # 78.53982

# 带多个参数的函数
calculate_bmi <- function(weight, height) {
# weight: 体重(kg)
# height: 身高(m)
bmi <- weight / (height^2)

# 返回BMI值和健康状况
if (bmi < 18.5) {
status <- "偏瘦"
} else if (bmi < 25) {
status <- "正常"
} else if (bmi < 30) {
status <- "偏胖"
} else {
status <- "肥胖"
}

# 返回列表
return(list(bmi = bmi, status = status))
}

# 使用函数
result <- calculate_bmi(70, 1.75)
print(paste("BMI:", round(result$bmi, 2))) # BMI: 22.86
print(paste("状态:", result$status)) # 状态: 正常

# 带默认参数的函数
greet <- function(name, greeting = "Hello") {
message <- paste(greeting, name)
return(message)
}

print(greet("Alice")) # "Hello Alice"
print(greet("Bob", "Good morning")) # "Good morning Bob"

2. 函数作用域

理解作用域对于编写正确的函数非常重要。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 全局变量 vs 局部变量
global_var <- 100

test_scope <- function() {
local_var <- 50 # 局部变量,只在函数内可见
global_var <- 200 # 创建了一个局部变量,不影响全局变量
print(paste("函数内 global_var:", global_var)) # 200
print(paste("函数内 local_var:", local_var)) # 50
}

test_scope()
print(paste("函数外 global_var:", global_var)) # 100
# print(local_var) # 错误!local_var在函数外不存在

# 使用<<-修改全局变量(慎用)
modify_global <- function() {
global_var <<- 300 # 使用<<-修改全局变量
}

modify_global()
print(global_var) # 300

3. 高阶函数

R支持函数式编程,可以将函数作为参数传递。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# apply系列函数
# apply: 对矩阵的行或列应用函数
mat <- matrix(1:12, nrow=3)
row_sums <- apply(mat, 1, sum) # 1表示行,计算每行的和
col_means <- apply(mat, 2, mean) # 2表示列,计算每列的平均值

# lapply: 对列表的每个元素应用函数,返回列表
numbers_list <- list(a = 1:5, b = 6:10, c = 11:15)
means_list <- lapply(numbers_list, mean)

# sapply: 类似lapply,但尝试简化结果为向量或矩阵
means_vector <- sapply(numbers_list, mean) # 返回向量

# tapply: 按分组应用函数
ages <- c(23, 25, 27, 22, 24, 26)
groups <- c("A", "B", "A", "B", "A", "B")
group_means <- tapply(ages, groups, mean) # 计算每组的平均年龄

数据导入与导出

在实际工作中,我们经常需要从外部文件读取数据或将处理结果保存到文件。

1. CSV文件

CSV是最常用的数据交换格式之一。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 写入CSV文件
# 创建示例数据
sales_data <- data.frame(
month = c("Jan", "Feb", "Mar", "Apr"),
revenue = c(10000, 12000, 15000, 13000),
profit = c(3000, 3500, 4500, 4000)
)

# 保存为CSV
write.csv(sales_data, "sales_2024.csv", row.names = FALSE)

# 读取CSV文件
data_from_csv <- read.csv("sales_2024.csv")
print(data_from_csv)

# 处理更复杂的CSV
# 指定分隔符、编码、缺失值等
data <- read.csv("data.csv",
sep = ",", # 分隔符
header = TRUE, # 第一行是否为列名
na.strings = c("NA", "N/A", ""), # 缺失值标记
stringsAsFactors = FALSE) # 字符串不转为因子

2. Excel文件

处理Excel文件需要额外的包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 安装和加载readxl包
install.packages("readxl")
library(readxl)

# 读取Excel文件
excel_data <- read_excel("data.xlsx", sheet = 1) # 读取第一个工作表

# 或指定工作表名称
excel_data <- read_excel("data.xlsx", sheet = "Sales")

# 写入Excel(需要writexl包)
install.packages("writexl")
library(writexl)
write_xlsx(sales_data, "output.xlsx")

3. R数据文件

R有自己的数据格式,适合保存R对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 保存单个对象
saveRDS(student_data, "student_data.rds")

# 读取RDS文件
loaded_data <- readRDS("student_data.rds")

# 保存多个对象
save(student_data, sales_data, file = "my_data.RData")

# 加载RData文件
load("my_data.RData") # 对象会自动加载到环境中

# 保存整个工作空间
save.image("workspace.RData")

数据清洗与处理

数据清洗是数据分析中最耗时但也最重要的步骤。真实世界的数据通常需要大量清理才能使用。

1. 处理缺失值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 创建包含缺失值的数据
test_data <- data.frame(
id = 1:6,
value1 = c(10, NA, 30, 40, NA, 60),
value2 = c(100, 200, NA, 400, 500, NA)
)

# 检测缺失值
is.na(test_data) # 返回逻辑矩阵
complete.cases(test_data) # 检查完整的行
sum(is.na(test_data)) # 缺失值总数

# 处理缺失值
# 方法1:删除包含NA的行
clean_data1 <- na.omit(test_data)

# 方法2:用特定值填充
test_data$value1[is.na(test_data$value1)] <- 0

# 方法3:用平均值填充
mean_val <- mean(test_data$value2, na.rm = TRUE)
test_data$value2[is.na(test_data$value2)] <- mean_val

# 方法4:向前或向后填充(需要zoo包)
install.packages("zoo")
library(zoo)
test_data$value1 <- na.fill(test_data$value1, "extend")

2. 数据转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 数据类型转换
df <- data.frame(
numbers = c("1", "2", "3"),
dates = c("2024-01-01", "2024-02-01", "2024-03-01"),
categories = c("A", "B", "A")
)

df$numbers <- as.numeric(df$numbers)
df$dates <- as.Date(df$dates)
df$categories <- as.factor(df$categories)

# 数据标准化和归一化
# 标准化(z-score)
standardize <- function(x) {
(x - mean(x, na.rm = TRUE)) / sd(x, na.rm = TRUE)
}

# 归一化(0-1范围)
normalize <- function(x) {
(x - min(x, na.rm = TRUE)) / (max(x, na.rm = TRUE) - min(x, na.rm = TRUE))
}

# 应用转换
data <- data.frame(
height = c(165, 170, 175, 180, 185),
weight = c(60, 65, 70, 75, 80)
)

data$height_std <- standardize(data$height)
data$weight_norm <- normalize(data$weight)

3. 数据重塑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 宽格式转长格式(需要reshape2包)
install.packages("reshape2")
library(reshape2)

# 宽格式数据
wide_data <- data.frame(
id = 1:3,
jan = c(100, 110, 120),
feb = c(105, 115, 125),
mar = c(110, 120, 130)
)

# 转为长格式
long_data <- melt(wide_data,
id.vars = "id",
variable.name = "month",
value.name = "sales")

# 长格式转宽格式
wide_again <- dcast(long_data, id ~ month, value.var = "sales")

数据可视化基础

数据可视化是理解数据的重要工具。R提供了强大的绘图功能。

1. 基础绘图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 准备数据
x <- 1:10
y <- x^2

# 散点图
plot(x, y,
main = "二次函数图像", # 标题
xlab = "X轴", # X轴标签
ylab = "Y轴", # Y轴标签
col = "blue", # 颜色
pch = 16) # 点的形状

# 添加线条
lines(x, y, col = "red", lwd = 2) # lwd是线宽

# 直方图
data <- rnorm(1000, mean = 100, sd = 15) # 生成正态分布数据
hist(data,
breaks = 30, # 分组数
main = "正态分布直方图",
xlab = "值",
col = "lightblue",
border = "black")

# 箱线图
boxplot(data,
main = "数据分布箱线图",
ylab = "值",
col = "lightgreen")

# 条形图
categories <- c("A", "B", "C", "D")
values <- c(25, 40, 35, 50)
barplot(values,
names.arg = categories,
main = "分类数据条形图",
xlab = "类别",
ylab = "数值",
col = rainbow(4)) # 使用彩虹色

# 饼图
pie(values,
labels = categories,
main = "数据占比饼图",
col = c("red", "blue", "green", "yellow"))

2. 多图布局

1
2
3
4
5
6
7
8
9
10
11
# 设置图形布局
par(mfrow = c(2, 2)) # 2行2列的布局

# 绘制四个图
plot(1:10, type = "l", main = "线图")
hist(rnorm(100), main = "直方图")
boxplot(rnorm(100), main = "箱线图")
barplot(c(3, 5, 2, 4), main = "条形图")

# 恢复默认布局
par(mfrow = c(1, 1))

3. ggplot2高级绘图

ggplot2是R中最流行的绘图包,提供了更优雅的绘图语法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 安装和加载ggplot2
install.packages("ggplot2")
library(ggplot2)

# 创建示例数据
df <- data.frame(
x = rep(1:10, 3),
y = c(1:10, (1:10)^0.5, (1:10)^2),
group = rep(c("线性", "平方根", "平方"), each = 10)
)

# 基础ggplot图
p <- ggplot(df, aes(x = x, y = y, color = group)) +
geom_point(size = 3) + # 添加点
geom_line(size = 1) + # 添加线
labs(title = "不同函数的比较",
x = "X值",
y = "Y值",
color = "函数类型") +
theme_minimal() + # 使用简洁主题
theme(plot.title = element_text(hjust = 0.5)) # 标题居中

print(p)

# 分面图(多个子图)
p_facet <- ggplot(df, aes(x = x, y = y)) +
geom_point() +
geom_smooth(method = "loess") + # 添加平滑曲线
facet_wrap(~ group, scales = "free_y") + # 按group分面
theme_bw()

print(p_facet)

基础统计分析

R的强大之处在于其统计分析能力。让我们学习一些基础的统计方法。

1. 描述性统计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 生成示例数据
set.seed(123) # 设置随机种子,保证结果可重现
data <- rnorm(100, mean = 50, sd = 10)

# 基本统计量
mean(data) # 均值
median(data) # 中位数
sd(data) # 标准差
var(data) # 方差
min(data) # 最小值
max(data) # 最大值
range(data) # 范围(最小值和最大值)
quantile(data, c(0.25, 0.75)) # 四分位数

# 综合统计摘要
summary(data)

# 自定义描述统计函数
describe_data <- function(x) {
list(
n = length(x),
mean = mean(x, na.rm = TRUE),
median = median(x, na.rm = TRUE),
sd = sd(x, na.rm = TRUE),
min = min(x, na.rm = TRUE),
max = max(x, na.rm = TRUE),
q25 = quantile(x, 0.25, na.rm = TRUE),
q75 = quantile(x, 0.75, na.rm = TRUE)
)
}

stats <- describe_data(data)
print(stats)

2. 假设检验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# t检验
# 单样本t检验:检验均值是否等于某个值
t.test(data, mu = 50) # 检验均值是否等于50

# 双样本t检验:比较两组数据的均值
group1 <- rnorm(50, mean = 50, sd = 10)
group2 <- rnorm(50, mean = 52, sd = 10)
t.test(group1, group2) # 默认是韦尔奇t检验(方差不等)
t.test(group1, group2, var.equal = TRUE) # 方差相等的t检验

# 配对t检验
before <- rnorm(30, mean = 100, sd = 15)
after <- before + rnorm(30, mean = 5, sd = 5) # 有改善
t.test(before, after, paired = TRUE)

# 卡方检验
# 创建列联表
observed <- matrix(c(20, 30, 25, 25), nrow = 2)
chisq.test(observed)

# 方差分析(ANOVA)
# 创建示例数据
treatment <- factor(rep(c("A", "B", "C"), each = 20))
response <- c(rnorm(20, mean = 10),
rnorm(20, mean = 12),
rnorm(20, mean = 11))

# 单因素方差分析
model <- aov(response ~ treatment)
summary(model)

# 事后检验(如果ANOVA显著)
TukeyHSD(model)

3. 相关性分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 创建相关数据
x <- rnorm(100)
y <- 2 * x + rnorm(100, sd = 0.5) # y与x有较强相关性
z <- rnorm(100) # z与x、y无关

data <- data.frame(x = x, y = y, z = z)

# 相关系数
cor(x, y) # 皮尔逊相关系数
cor(data) # 相关矩阵
cor(data, method = "spearman") # 斯皮尔曼等级相关

# 相关性检验
cor.test(x, y) # 检验相关性是否显著

# 可视化相关矩阵
install.packages("corrplot")
library(corrplot)
cor_matrix <- cor(data)
corrplot(cor_matrix, method = "circle", type = "upper")

线性回归

线性回归是最基础也是最重要的统计模型之一。

1. 简单线性回归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 创建示例数据
set.seed(123)
x <- 1:100
y <- 2 * x + 3 + rnorm(100, sd = 10) # y = 2x + 3 + 噪声
data <- data.frame(x = x, y = y)

# 建立线性模型
model <- lm(y ~ x, data = data) # y ~ x 表示 y 对 x 回归

# 查看模型结果
summary(model) # 详细的统计结果
coef(model) # 系数
confint(model) # 系数的置信区间

# 预测
new_data <- data.frame(x = c(101, 102, 103))
predictions <- predict(model, newdata = new_data)
print(predictions)

# 带置信区间的预测
predict(model, newdata = new_data, interval = "confidence")
predict(model, newdata = new_data, interval = "prediction")

# 可视化
plot(data$x, data$y,
main = "线性回归",
xlab = "X", ylab = "Y")
abline(model, col = "red", lwd = 2) # 添加回归线

# 或使用ggplot2
library(ggplot2)
ggplot(data, aes(x = x, y = y)) +
geom_point() +
geom_smooth(method = "lm", se = TRUE) + # se=TRUE显示置信带
labs(title = "线性回归分析")

2. 多元线性回归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 创建多变量数据
n <- 100
x1 <- rnorm(n)
x2 <- rnorm(n)
x3 <- rnorm(n)
y <- 2*x1 + 3*x2 - x3 + 5 + rnorm(n, sd = 2)
data <- data.frame(y, x1, x2, x3)

# 建立多元回归模型
model_multi <- lm(y ~ x1 + x2 + x3, data = data)
summary(model_multi)

# 逐步回归(变量选择)
# 向前选择
model_null <- lm(y ~ 1, data = data) # 空模型
model_full <- lm(y ~ ., data = data) # 全模型

# 使用AIC准则进行逐步回归
step_model <- step(model_null,
scope = list(lower = model_null, upper = model_full),
direction = "forward")

3. 模型诊断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 残差分析
residuals <- residuals(model)
fitted_values <- fitted(model)

# 残差图
par(mfrow = c(2, 2))
plot(model) # 自动生成4个诊断图
par(mfrow = c(1, 1))

# 手动创建诊断图
# 1. 残差vs拟合值(检查线性假设和方差齐性)
plot(fitted_values, residuals,
main = "残差 vs 拟合值",
xlab = "拟合值", ylab = "残差")
abline(h = 0, col = "red", lty = 2)

# 2. Q-Q图(检查正态性假设)
qqnorm(residuals)
qqline(residuals, col = "red")

# 3. 检查异常值和影响点
cooksd <- cooks.distance(model)
plot(cooksd, type = "h",
main = "Cook's距离",
ylab = "Cook's距离")
abline(h = 4/length(cooksd), col = "red", lty = 2)

# VIF检查多重共线性(需要car包)
install.packages("car")
library(car)
vif(model_multi) # VIF > 5或10表示可能存在多重共线性

实用技巧和最佳实践

1. 代码组织

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 项目结构建议
# project/
# ├── data/ # 原始数据
# ├── scripts/ # R脚本
# ├── output/ # 结果输出
# └── functions/ # 自定义函数

# 设置工作目录
setwd("~/my_project")
getwd() # 查看当前工作目录

# 使用相对路径
data <- read.csv("data/my_data.csv")
source("functions/my_functions.R") # 加载自定义函数文件

# 清理环境
rm(list = ls()) # 清空所有变量
gc() # 垃圾回收,释放内存

2. 错误处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# try-catch结构
safe_divide <- function(x, y) {
result <- tryCatch({
x / y
}, error = function(e) {
print(paste("错误:", e$message))
return(NA)
}, warning = function(w) {
print(paste("警告:", w$message))
return(x / y)
})
return(result)
}

# 测试函数
safe_divide(10, 2) # 正常:5
safe_divide(10, 0) # 产生警告:Inf
safe_divide(10, "a") # 产生错误:NA

# 输入验证
robust_mean <- function(x) {
if (!is.numeric(x)) {
stop("输入必须是数值型")
}
if (length(x) == 0) {
warning("输入为空向量")
return(NA)
}
return(mean(x, na.rm = TRUE))
}

3. 性能优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# 向量化操作(避免循环)
# 慢速方法
slow_sum <- function(n) {
total <- 0
for (i in 1:n) {
total <- total + i
}
return(total)
}

# 快速方法
fast_sum <- function(n) {
sum(1:n)
}

# 比较运行时间
system.time(slow_sum(1000000))
system.time(fast_sum(1000000))

# 预分配内存
# 慢速方法
slow_grow <- function(n) {
vec <- c()
for (i in 1:n) {
vec <- c(vec, i) # 每次都重新分配内存
}
return(vec)
}

# 快速方法
fast_grow <- function(n) {
vec <- numeric(n) # 预分配内存
for (i in 1:n) {
vec[i] <- i
}
return(vec)
}

# 使用apply函数代替循环
# 计算矩阵每行的标准差
mat <- matrix(rnorm(10000), nrow = 100)

# 使用apply(推荐)
row_sds <- apply(mat, 1, sd)

# 使用循环(不推荐)
row_sds_loop <- numeric(nrow(mat))
for (i in 1:nrow(mat)) {
row_sds_loop[i] <- sd(mat[i, ])
}
打赏
微信 | Wechat