R语言是一种专门用于统计分析和数据可视化的编程语言。简单来说,它是一个强大的”计算器”,不仅能做加减乘除,还能处理复杂的数据分析任务。
提示:安装路径中避免出现中文和空格,例如
C:\Program Files\R\R-4.x.x是推荐的路径格式。
RStudio是R语言的集成开发环境(IDE)。如果把R比作汽车的发动机,那么RStudio就是一辆完整的汽车——它让R更易用、更美观、功能更强大。
虽然R自带了一个简单的界面,但RStudio提供了: - 代码高亮显示(不同颜色区分代码元素) - 代码自动补全 - 项目管理功能 - 内置帮助系统 - 更好的图形显示
安装过程非常简单,按照向导点击”下一步”即可。重要提示:必须先安装R,再安装RStudio。
打开RStudio后,你会看到四个主要面板:
这是你编写代码的地方。你可以: -
创建新的R脚本文件(File → New File → R Script) - 保存代码以便下次使用 -
选中代码按 Ctrl+Enter 运行
这是执行代码的地方。你可以: - 直接输入代码并按回车执行 - 查看代码运行结果 - 查看错误和警告信息
# 这是一个简单的加法运算
# R会自动计算并输出结果
1 + 1
## [1] 2
包含多个标签页: - Files:文件浏览器,显示当前目录的文件 - Plots:显示绘制的图形 - Packages:管理已安装的R包 - Help:查看函数帮助文档 - Viewer:显示本地网页内容
R项目是RStudio提供的一种工作组织方式。它将所有相关的代码、数据、结果保存在一个文件夹中,方便管理和分享。
创建后会生成一个 .Rproj
文件,双击它即可打开整个项目。
工作目录是R默认读取和保存文件的文件夹。就像你在电脑上有一个”我的文档”文件夹一样,R也需要知道从哪里找文件、把文件存到哪里。
使用 getwd() 函数:
# getwd() 函数用于获取当前工作目录
# 工作目录是R默认读取和保存文件的文件夹
getwd()
## [1] "C:/Users/XTS-green/Desktop/medical_student_rescue_plan-main/R语言与生信分析/R语言/001R语言基础"
使用 setwd() 函数:
# setwd() 函数用于设置工作目录
# 注意:Windows系统中路径使用正斜杠 / 或双反斜杠 \\
# 单反斜杠 \ 会被R识别为转义字符,导致错误
setwd("C:/Users/你的用户名/Documents/my_project")
注意:Windows系统中路径使用正斜杠
/或双反斜杠\\,不能使用单反斜杠\。
更简单的方法: 1. 点击菜单:Session → Set Working Directory → Choose Directory 2. 或在Files面板中导航到目标文件夹,点击”More” → “Set As Working Directory”
注释是给人看的说明文字,R在执行代码时会忽略注释内容。注释的作用是: 解释代码的功能 标记重要信息 暂时禁用某些代码
使用 # 符号:
# 使用 <- 进行赋值,这是R语言最常用的赋值方式
# 将数值10存储到变量x中
x <- 10
# 使用变量x进行计算
# R会输出计算结果
x + 5
## [1] 15
良好的代码排版让代码更易读:
# 创建数值向量x,包含1到5
x <- c(1, 2, 3, 4, 5)
# 创建数值向量y,包含偶数序列
y <- c(2, 4, 6, 8, 10)
# 计算向量x的平均值
mean_x <- mean(x)
# 计算向量y的平均值
mean_y <- mean(y)
# 将两个平均值相加
result <- mean_x + mean_y
# 输出结果
result
## [1] 9
表达式是可以被R计算并产生结果的代码片段。最简单的表达式就是数学运算:
# 加法表达式:1加2
1 + 2
## [1] 3
# 乘法表达式:3乘以4
3 * 4
## [1] 12
# 函数调用表达式:计算16的平方根
sqrt(16)
## [1] 4
赋值就是把一个值存储到变量中,以便后续使用。可以理解为给数据起一个名字。
R语言有多种赋值方式:
# 方式1:使用 <- 赋值(推荐)
# 将数值10存储到变量x中
x <- 10
x
## [1] 10
# 方式2:使用 = 赋值
# 将数值20存储到变量y中
y = 20
y
## [1] 20
# 方式3:使用 -> 赋值(从左向右)
# 将数值30存储到变量z中
30 -> z
z
## [1] 30
| 符号 | 方向 | 推荐使用场景 |
|---|---|---|
<- |
左箭头(向左赋值) | R语言传统写法,推荐使用 |
= |
等号 | 函数参数设置时使用 |
-> |
右箭头(向右赋值) | 较少使用,管道操作时可能用到 |
# 使用 <- 进行赋值并计算
# 先计算5+3得到8,再将8存储到result变量中
result <- 5 + 3
result
## [1] 8
R支持所有常见的数学运算:
# 定义两个变量
a <- 10
b <- 3
# 加法:10 + 3 = 13
a + b
## [1] 13
# 减法:10 - 3 = 7
a - b
## [1] 7
# 乘法:10 * 3 = 30
a * b
## [1] 30
# 除法:10 / 3 = 3.333...
a / b
## [1] 3.333333
# 幂运算:10的3次方 = 1000
a ^ b
## [1] 1000
# 取余数:10除以3的余数 = 1
a %% b
## [1] 1
# 整除:10除以3的整数部分 = 3
a %/% b
## [1] 3
| 运算符 | 含义 | 示例 | 结果 |
|---|---|---|---|
+ |
加法 | 5 + 3 | 8 |
- |
减法 | 5 - 3 | 2 |
* |
乘法 | 5 * 3 | 15 |
/ |
除法 | 5 / 3 | 1.667 |
^ |
幂运算 | 5 ^ 3 | 125 |
%% |
取余数 | 5 %% 3 | 2 |
%/% |
整除 | 5 %/% 3 | 1 |
关系运算用于比较两个值,结果是逻辑值(TRUE或FALSE):
# 定义两个变量用于比较
x <- 5
y <- 10
# 大于:5 > 10 吗?结果为 FALSE
x > y
## [1] FALSE
# 小于:5 < 10 吗?结果为 TRUE
x < y
## [1] TRUE
# 大于等于:5 >= 5 吗?结果为 TRUE
x >= 5
## [1] TRUE
# 小于等于:10 <= 10 吗?结果为 TRUE
y <= 10
## [1] TRUE
# 等于:x的值等于5吗?结果为 TRUE
# 注意:判断相等用双等号 ==
x == 5
## [1] TRUE
# 不等于:x的值不等于5吗?结果为 FALSE
x != 5
## [1] FALSE
| 运算符 | 含义 | 示例 |
|---|---|---|
> |
大于 | 5 > 3 返回 TRUE |
< |
小于 | 5 < 3 返回 FALSE |
>= |
大于等于 | 5 >= 5 返回 TRUE |
<= |
小于等于 | 5 <= 3 返回 FALSE |
== |
等于 | 5 == 5 返回 TRUE |
!= |
不等于 | 5 != 3 返回 TRUE |
重要提示:判断相等用
==(双等号),单等号=是赋值!
逻辑运算用于组合多个条件:
x <- 5
# 与运算(AND):两个条件都为TRUE才返回TRUE
# x > 3 且 x < 10 吗?结果为 TRUE
x > 3 & x < 10
## [1] TRUE
# 或运算(OR):只要有一个条件为TRUE就返回TRUE
# x < 3 或 x > 10 吗?结果为 FALSE
x < 3 | x > 10
## [1] FALSE
# 非运算(NOT):取反
# !TRUE 结果为 FALSE
!TRUE
## [1] FALSE
# 对逻辑表达式取反
# x > 10 为 FALSE,取反后为 TRUE
!(x > 10)
## [1] TRUE
# 定义两个逻辑变量
a <- TRUE
b <- FALSE
# 与运算:TRUE AND FALSE = FALSE
a & b
## [1] FALSE
# 或运算:TRUE OR FALSE = TRUE
a | b
## [1] TRUE
# 非运算:NOT TRUE = FALSE
!a
## [1] FALSE
&/| 与
&&/|| 的区别:
# 创建两个逻辑向量
x <- c(TRUE, FALSE, TRUE)
y <- c(FALSE, FALSE, TRUE)
# & 是向量化运算,对每个元素逐一进行AND运算
# TRUE & FALSE = FALSE, FALSE & FALSE = FALSE, TRUE & TRUE = TRUE
x & y
## [1] FALSE FALSE TRUE
# && 是标量运算,只比较第一个元素
# TRUE && FALSE = FALSE
TRUE && FALSE
## [1] FALSE
# TRUE && TRUE = TRUE
TRUE && TRUE
## [1] TRUE
# || 是标量运算,只比较第一个元素
# TRUE || FALSE = TRUE
TRUE || FALSE
## [1] TRUE
| 运算符 | 说明 |
|---|---|
& |
向量化AND,对每个元素进行运算 |
&& |
标量AND,只用于单个逻辑值(if条件判断) |
| |
向量化OR,对每个元素进行运算 |
|| |
标量OR,只用于单个逻辑值(if条件判断) |
建议:处理向量时用
&和|;if条件判断时用&&和||。
R内置了丰富的数学函数:
# 定义一个负数
x <- -4.5
# abs():取绝对值,|-4.5| = 4.5
abs(x)
## [1] 4.5
# sqrt():计算平方根,√16 = 4
sqrt(16)
## [1] 4
# log():自然对数(以e为底),ln(100) ≈ 4.605
log(100)
## [1] 4.60517
# log10():以10为底的对数,log10(100) = 2
log10(100)
## [1] 2
# log2():以2为底的对数,log2(8) = 3
log2(8)
## [1] 3
# exp():e的x次方,e^1 ≈ 2.718
exp(1)
## [1] 2.718282
# sin():正弦函数,sin(π/2) = 1
# pi 是R内置的圆周率常量
sin(pi/2)
## [1] 1
# cos():余弦函数,cos(0) = 1
cos(0)
## [1] 1
# tan():正切函数,tan(π/4) ≈ 1
tan(pi/4)
## [1] 1
# round():四舍五入到指定小数位
# 将3.14159保留2位小数 = 3.14
round(3.14159, 2)
## [1] 3.14
# ceiling():向上取整,3.2 → 4
ceiling(3.2)
## [1] 4
# floor():向下取整,3.8 → 3
floor(3.8)
## [1] 3
# sign():符号函数,负数返回-1,正数返回1,零返回0
sign(-5)
## [1] -1
| 函数 | 功能 | 示例 |
|---|---|---|
abs(x) |
绝对值 | abs(-5) = 5 |
sqrt(x) |
平方根 | sqrt(16) = 4 |
log(x) |
自然对数 | log(2.718) ≈ 1 |
log10(x) |
以10为底的对数 | log10(100) = 2 |
log2(x) |
以2为底的对数 | log2(8) = 3 |
exp(x) |
e的x次方 | exp(1) ≈ 2.718 |
sin(x) |
正弦 | sin(0) = 0 |
cos(x) |
余弦 | cos(0) = 1 |
tan(x) |
正切 | tan(0) = 0 |
round(x, n) |
四舍五入到n位小数 | round(3.14, 1) = 3.1 |
ceiling(x) |
向上取整 | ceiling(3.1) = 4 |
floor(x) |
向下取整 | floor(3.9) = 3 |
sign(x) |
符号函数 | sign(-5) = -1 |
变量名必须遵循以下规则:
# 以下是合法的变量名
# 使用下划线连接(推荐风格)
my_data <- 1
# 使用点连接
my.data <- 2
# 驼峰命名法
myData <- 3
# 输出变量值
my_data
## [1] 1
命名规则: 1. 只能包含字母、数字、下划线
_ 和点 . 2.
必须以字母或点开头(不能以数字开头) 3. 不能使用R的保留字(如
if、else、for、while等)
4. 区分大小写(myVar 和 myvar
是不同的变量)
# 这是错误的命名方式(以数字开头),会报错
2nd_value <- 10
使用 ls() 函数列出当前环境中的所有变量:
# 创建几个变量
a <- 1
b <- 2
my_var <- 3
# ls() 列出所有变量名
ls()
## [1] "a" "b" "mean_x" "mean_y" "my.data" "my_data" "my_var"
## [8] "myData" "result" "x" "y" "z"
使用 ls.str() 查看变量及其结构:
# ls.str() 显示变量名和简要结构信息
ls.str()
## a : num 1
## b : num 2
## mean_x : num 3
## mean_y : num 6
## my.data : num 2
## my_data : num 1
## my_var : num 3
## myData : num 3
## result : num 8
## x : num -4.5
## y : logi [1:3] FALSE FALSE TRUE
## z : num 30
# 创建一个临时变量
temp_var <- 100
temp_var
## [1] 100
# 使用 rm() 函数删除变量
rm(temp_var)
# 此时再输出 temp_var 会报错(变量已不存在)
# temp_var
# 创建三个变量
x <- 1
y <- 2
z <- 3
# 删除 x 和 y 两个变量
rm(x, y)
# 查看剩余变量,z 还在
ls()
## [1] "a" "b" "mean_x" "mean_y" "my.data" "my_data" "my_var"
## [8] "myData" "result" "z"
# 删除当前环境中的所有变量
# list = ls() 表示"所有变量组成的列表"
rm(list = ls())
警告:此操作会删除当前环境中的所有变量,请谨慎使用!
R提供了多个函数来查看对象的详细信息:
# 创建一个数值向量
my_vector <- c(1, 2, 3, 4, 5)
# str():显示对象的结构(structure)
# 输出:类型、长度、内容预览
str(my_vector)
## num [1:5] 1 2 3 4 5
# class():显示对象的类
# 数值向量的类是 "numeric"
class(my_vector)
## [1] "numeric"
# mode():显示存储模式
# 表示数据的存储方式
mode(my_vector)
## [1] "numeric"
# typeof():显示底层类型
# R内部存储的具体类型
typeof(my_vector)
## [1] "double"
# length():显示长度(元素个数)
length(my_vector)
## [1] 5
| 函数 | 作用 | 返回内容 |
|---|---|---|
str() |
显示对象结构 | 类型、维度、内容预览 |
class() |
显示对象类 | 面向对象的类属性 |
mode() |
显示存储模式 | 数据的存储方式 |
typeof() |
显示底层类型 | R内部存储类型 |
length() |
显示长度 | 元素个数 |
# 创建一个列表(包含不同类型的数据)
my_list <- list(name = "张三", age = 25, scores = c(85, 90, 78))
# str() 显示列表的完整结构
# 可以看到每个元素的名称、类型和内容
str(my_list)
## List of 3
## $ name : chr "张三"
## $ age : num 25
## $ scores: num [1:3] 85 90 78
# class() 显示对象是列表类型
class(my_list)
## [1] "list"
# length() 显示列表有3个元素
length(my_list)
## [1] 3
R语言有几种基本数据类型,理解它们是学习R的基础。
数值型是最常用的数据类型,包括整数和双精度浮点数:
# 双精度浮点数(带小数点的数)
x <- 3.14
class(x)
## [1] "numeric"
# 整数:加 L 后缀表示整数类型
y <- 100L
class(y)
## [1] "integer"
# is.numeric():检查是否为数值型
# 整数和双精度都是数值型
is.numeric(x)
## [1] TRUE
# is.integer():检查是否为整数类型
is.integer(y)
## [1] TRUE
# is.double():检查是否为双精度浮点数
is.double(x)
## [1] TRUE
整数与双精度的区别: - 整数:不带小数点的整数,加
L 后缀表示 - 双精度:带小数点的数,R默认的数值类型
# typeof() 查看R内部存储类型
# 3.14 是双精度浮点数
typeof(3.14)
## [1] "double"
# 不加L,R默认存储为双精度
typeof(3)
## [1] "double"
# 加L,存储为整数
typeof(3L)
## [1] "integer"
字符型用于存储文本数据:
# 使用双引号创建字符串
name <- "张三"
class(name)
## [1] "character"
# 使用单引号也可以创建字符串
message <- 'Hello World'
class(message)
## [1] "character"
# 字符串中包含引号:外双内单,或外单内双
sentence <- "这是一个包含'引号'的字符串"
sentence
## [1] "这是一个包含'引号'的字符串"
# nchar():计算字符串的字符数
nchar("你好世界")
## [1] 4
逻辑型只有两个值:TRUE 和 FALSE:
# 定义逻辑变量
flag1 <- TRUE
flag2 <- FALSE
# 查看类型
class(flag1)
## [1] "logical"
# 比较运算返回逻辑值
# 5 > 3 为 TRUE
5 > 3
## [1] TRUE
# 10 == 20 为 FALSE
10 == 20
## [1] FALSE
# 数值转逻辑:非0为TRUE,0为FALSE
as.logical(1)
## [1] TRUE
as.logical(0)
## [1] FALSE
# 逻辑转数值:TRUE为1,FALSE为0
as.numeric(TRUE)
## [1] 1
因子型用于存储分类数据,如性别、血型等:
# 创建因子:将字符向量转换为因子
gender <- factor(c("男", "女", "男", "男", "女"))
gender
## [1] 男 女 男 男 女
## Levels: 男 女
# levels():查看因子的水平(所有可能的类别)
levels(gender)
## [1] "男" "女"
# nlevels():查看水平的数量
nlevels(gender)
## [1] 2
# 指定水平的顺序
# levels参数定义所有可能的水平(包括数据中没有的)
blood_type <- factor(c("A", "B", "O", "AB", "A"),
levels = c("A", "B", "AB", "O"))
blood_type
## [1] A B O AB A
## Levels: A B AB O
# 创建有序因子(有大小关系)
# ordered = TRUE 表示这是一个有序因子
status <- factor(c("低", "中", "高", "低"),
levels = c("低", "中", "高"),
ordered = TRUE)
status
## [1] 低 中 高 低
## Levels: 低 < 中 < 高
# 有序因子可以比较大小
# "低" < "高" 为 TRUE
status[1] < status[3]
## [1] TRUE
R有专门的日期和时间类型:
# Sys.Date():获取当前日期
today <- Sys.Date()
today
## [1] "2026-03-19"
# 查看类型:Date类型
class(today)
## [1] "Date"
# as.Date():将字符串转换为日期
my_date <- as.Date("2024-01-15")
my_date
## [1] "2024-01-15"
# 日期可以进行算术运算
# 日期加7天
my_date + 7
## [1] "2024-01-22"
# 自定义日期格式
# format参数指定输入格式
as.Date("2024/03/15", format = "%Y/%m/%d")
## [1] "2024-03-15"
# Sys.time():获取当前日期和时间
now <- Sys.time()
now
## [1] "2026-03-19 20:48:30 CST"
# 查看类型:POSIXct类型(包含日期和时间)
class(now)
## [1] "POSIXct" "POSIXt"
# format():格式化日期时间输出
# %Y年%m月%d日 %H:%M:%S 表示:年月日 时分秒
format(now, "%Y年%m月%d日 %H:%M:%S")
## [1] "2026年03月19日 20:48:30"
常用日期格式符号:
| 符号 | 含义 | 示例 |
|---|---|---|
%Y |
四位年份 | 2024 |
%y |
两位年份 | 24 |
%m |
月份(01-12) | 03 |
%d |
日期(01-31) | 15 |
%H |
小时(00-23) | 14 |
%M |
分钟(00-59) | 30 |
%S |
秒(00-59) | 45 |
向量是R中最基本的数据结构,它是一组相同类型数据的有序集合。可以把向量理解为一个”一排数据”。
使用 c() 函数创建向量(c代表combine,合并):
# 创建数值向量
# c() 函数将多个值合并成一个向量
numbers <- c(1, 2, 3, 4, 5)
numbers
## [1] 1 2 3 4 5
# 创建字符向量
names <- c("张三", "李四", "王五")
names
## [1] "张三" "李四" "王五"
# 创建逻辑向量
logics <- c(TRUE, FALSE, TRUE, FALSE)
logics
## [1] TRUE FALSE TRUE FALSE
使用 seq() 创建等差序列:
# seq(from, to):从1到10,默认步长为1
seq(1, 10)
## [1] 1 2 3 4 5 6 7 8 9 10
# seq(from, to, by):从1到10,步长为2
# 结果:1, 3, 5, 7, 9
seq(1, 10, by = 2)
## [1] 1 3 5 7 9
# seq(from, to, length.out):从1到10,生成5个等间距的数
seq(1, 10, length.out = 5)
## [1] 1.00 3.25 5.50 7.75 10.00
使用 rep() 创建重复序列:
# rep(x, times):将1重复5次
rep(1, times = 5)
## [1] 1 1 1 1 1
# rep(x, times):将向量c(1,2)整体重复3次
# 结果:1, 2, 1, 2, 1, 2
rep(c(1, 2), times = 3)
## [1] 1 2 1 2 1 2
# rep(x, each):将向量中每个元素各重复3次
# 结果:1, 1, 1, 2, 2, 2
rep(c(1, 2), each = 3)
## [1] 1 1 1 2 2 2
使用 : 运算符创建连续整数:
# 从1到5的连续整数
1:5
## [1] 1 2 3 4 5
# 从5到1的递减序列
5:1
## [1] 5 4 3 2 1
可以为向量的每个元素命名:
# 创建分数向量
scores <- c(85, 90, 78, 92)
# 使用 names() 为每个元素命名
names(scores) <- c("语文", "数学", "英语", "物理")
scores
## 语文 数学 英语 物理
## 85 90 78 92
# 通过名称访问元素
scores["数学"]
## 数学
## 90
ages <- c(张三 = 25, 李四 = 30, 王五 = 28)
ages
## 张三 李四 王五
## 25 30 28
位置索引(从1开始,不是从0):
x <- c(10, 20, 30, 40, 50)
# 获取第1个元素
x[1]
## [1] 10
# 获取第1、3、5个元素
x[c(1, 3, 5)]
## [1] 10 30 50
# 获取第2到第4个元素
x[2:4]
## [1] 20 30 40
# 使用负号排除元素:排除第1个
x[-1]
## [1] 20 30 40 50
# 排除第1和第2个元素
x[-c(1, 2)]
## [1] 30 40 50
逻辑索引:
x <- c(10, 20, 30, 40, 50)
# 筛选大于25的元素
x[x > 25]
## [1] 30 40 50
# 筛选20到40之间的元素
x[x >= 20 & x <= 40]
## [1] 20 30 40
# 使用逻辑向量筛选
# TRUE表示保留,FALSE表示排除
x[c(TRUE, FALSE, TRUE, FALSE, TRUE)]
## [1] 10 30 50
名称索引:
# 创建带名称的向量
scores <- c(语文 = 85, 数学 = 90, 英语 = 78)
# 通过名称获取元素
scores["数学"]
## 数学
## 90
# 获取多个元素
scores[c("语文", "英语")]
## 语文 英语
## 85 78
[] 与 [[]] 的区别:
x <- c(a = 10, b = 20, c = 30)
# [] 返回命名的向量(保留名称)
x[1]
## a
## 10
# [[]] 返回元素的值(不保留名称)
x[[1]]
## [1] 10
x <- c(1, 2, 3, 4, 5)
# 修改第1个元素为10
x[1] <- 10
x
## [1] 10 2 3 4 5
# 同时修改多个元素
x[c(2, 4)] <- c(20, 40)
x
## [1] 10 20 3 40 5
# 添加第6个元素
x[6] <- 60
x
## [1] 10 20 3 40 5 60
# 使用 c() 在末尾添加元素
x <- c(x, 70, 80)
x
## [1] 10 20 3 40 5 60 70 80
# append():在指定位置插入元素
# 在第3个元素后插入100
append(x, 100, after = 3)
## [1] 10 20 3 100 40 5 60 70 80
向量化运算:R可以直接对向量进行数学运算,无需写循环:
a <- c(1, 2, 3, 4, 5)
b <- c(10, 20, 30, 40, 50)
# 向量加法:对应元素相加
a + b
## [1] 11 22 33 44 55
# 向量与标量运算:每个元素都乘以2
a * 2
## [1] 2 4 6 8 10
# 向量乘法:对应元素相乘
a * b
## [1] 10 40 90 160 250
# 函数也支持向量化:对每个元素求平方根
sqrt(a)
## [1] 1.000000 1.414214 1.732051 2.000000 2.236068
循环补齐:当两个向量长度不同时,R会自动循环较短的向量:
# 长度3的向量 + 长度6的向量
# 短向量会循环:c(1,2,3,1,2,3) + c(10,20,30,40,50,60)
c(1, 2, 3) + c(10, 20, 30, 40, 50, 60)
## [1] 11 22 33 41 52 63
# 长度2的向量 * 长度4的向量
# c(1,2,1,2) * c(10,20,30,40)
c(1, 2) * c(10, 20, 30, 40)
## [1] 10 40 30 80
矩阵是一个二维的数据结构,所有元素必须是相同类型。可以把它想象成一个表格,有行和列。
使用 matrix() 函数:
# matrix(data, nrow, ncol):创建矩阵
# data:数据,nrow:行数,ncol:列数
# 默认按列填充数据
m <- matrix(1:12, nrow = 3, ncol = 4)
m
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 2 5 8 11
## [3,] 3 6 9 12
# byrow = TRUE:按行填充数据
m2 <- matrix(1:12, nrow = 3, ncol = 4, byrow = TRUE)
m2
## [,1] [,2] [,3] [,4]
## [1,] 1 2 3 4
## [2,] 5 6 7 8
## [3,] 9 10 11 12
使用 cbind() 按列合并:
# cbind():column bind,按列合并向量
a <- c(1, 2, 3)
b <- c(4, 5, 6)
cbind(a, b)
## a b
## [1,] 1 4
## [2,] 2 5
## [3,] 3 6
使用 rbind() 按行合并:
# rbind():row bind,按行合并向量
rbind(a, b)
## [,1] [,2] [,3]
## a 1 2 3
## b 4 5 6
m <- matrix(1:12, nrow = 3, ncol = 4)
# dim():查看维度(行数,列数)
dim(m)
## [1] 3 4
# nrow():查看行数
nrow(m)
## [1] 3
# ncol():查看列数
ncol(m)
## [1] 4
# 设置行名和列名
rownames(m) <- c("行1", "行2", "行3")
colnames(m) <- c("列1", "列2", "列3", "列4")
m
## 列1 列2 列3 列4
## 行1 1 4 7 10
## 行2 2 5 8 11
## 行3 3 6 9 12
m <- matrix(1:12, nrow = 3, ncol = 4)
rownames(m) <- c("R1", "R2", "R3")
colnames(m) <- c("C1", "C2", "C3", "C4")
# 获取第1行第2列的元素
m[1, 2]
## [1] 4
# 获取第1行(所有列)
m[1, ]
## C1 C2 C3 C4
## 1 4 7 10
# 获取第2列(所有行)
m[, 2]
## R1 R2 R3
## 4 5 6
# 获取子矩阵:第1-2行,第2-3列
m[1:2, 2:3]
## C2 C3
## R1 4 7
## R2 5 8
# 通过名称获取元素
m["R2", "C3"]
## [1] 8
# 获取指定列
m[, c("C1", "C4")]
## C1 C4
## R1 1 10
## R2 2 11
## R3 3 12
m <- matrix(1:4, nrow = 2)
m
## [,1] [,2]
## [1,] 1 3
## [2,] 2 4
# t():矩阵转置(行列互换)
t(m)
## [,1] [,2]
## [1,] 1 2
## [2,] 3 4
# diag():提取对角线元素
diag(m)
## [1] 1 4
# diag():创建对角矩阵
diag(c(1, 2, 3))
## [,1] [,2] [,3]
## [1,] 1 0 0
## [2,] 0 2 0
## [3,] 0 0 3
# 矩阵乘法
A <- matrix(1:4, nrow = 2)
B <- matrix(5:8, nrow = 2)
#矩阵乘法很重要,在机器学习、深度学习中都有大量应用,忘记了的同学回去看看线代书
# %*%:矩阵乘法(线性代数中的矩阵乘法)
A %*% B
## [,1] [,2]
## [1,] 23 31
## [2,] 34 46
# *:对应元素相乘(不是矩阵乘法)
A * B
## [,1] [,2]
## [1,] 5 21
## [2,] 12 32
数组是矩阵的扩展,可以有多个维度。矩阵是二维数组,数组可以是三维、四维甚至更高维。
# array(data, dim):创建数组
# dim = c(3, 4, 2) 表示:3行、4列、2层
arr <- array(1:24, dim = c(3, 4, 2))
arr
## , , 1
##
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 2 5 8 11
## [3,] 3 6 9 12
##
## , , 2
##
## [,1] [,2] [,3] [,4]
## [1,] 13 16 19 22
## [2,] 14 17 20 23
## [3,] 15 18 21 24
# 获取第1层、第1行、第2列的元素
arr[1, 2, 1]
## [1] 4
# 获取第1层的所有数据(3行4列的矩阵)
arr[, , 1]
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 2 5 8 11
## [3,] 3 6 9 12
# 获取第2层的第1行所有数据
arr[1, , 2]
## [1] 13 16 19 22
列表是一种可以存储不同类型元素的数据结构。向量只能存同类型数据,而列表可以存任意类型,甚至可以嵌套其他列表。
# list():创建列表
# 列表可以包含不同类型的数据
my_list <- list(
name = "张三", # 字符型
age = 25, # 数值型
scores = c(85, 90, 78), # 向量
passed = TRUE # 逻辑型
)
my_list
## $name
## [1] "张三"
##
## $age
## [1] 25
##
## $scores
## [1] 85 90 78
##
## $passed
## [1] TRUE
my_list <- list(
name = "张三",
age = 25,
scores = c(85, 90, 78)
)
# 使用 $ 符号通过名称访问元素
my_list$name
## [1] "张三"
# 使用 [[ ]] 通过名称访问元素
my_list[["name"]]
## [1] "张三"
# 使用 [[ ]] 通过位置访问元素
my_list[[1]]
## [1] "张三"
# 使用 [ ] 返回子列表(仍是列表类型)
my_list["name"]
## $name
## [1] "张三"
# 获取前2个元素组成的子列表
my_list[1:2]
## $name
## [1] "张三"
##
## $age
## [1] 25
索引方式总结:
| 方式 | 返回类型 | 示例 |
|---|---|---|
$ |
元素本身 | list$name |
[[]] |
元素本身 | list[["name"]] 或 list[[1]] |
[] |
子列表 | list["name"] 或 list[1:2] |
my_list <- list(name = "张三", age = 25)
# 添加新元素:直接用 $ 赋值
my_list$gender <- "男"
my_list
## $name
## [1] "张三"
##
## $age
## [1] 25
##
## $gender
## [1] "男"
# 修改元素:重新赋值
my_list$age <- 26
my_list$age
## [1] 26
# 删除元素:赋值为 NULL
my_list$age <- NULL
my_list
## $name
## [1] "张三"
##
## $gender
## [1] "男"
列表可以嵌套列表,形成层级结构:
# 创建嵌套列表
student <- list(
info = list(
name = "张三",
age = 25
),
grades = list(
math = 90,
english = 85
)
)
# 访问嵌套元素:逐层访问
student$info$name
## [1] "张三"
student$grades$math
## [1] 90
数据框是R中最常用的数据结构,类似于Excel表格。每一列可以是不同类型的数据,但同一列必须是相同类型。
# data.frame():创建数据框
# 每个参数是一列,列名就是参数名
df <- data.frame(
name = c("张三", "李四", "王五"), # 字符型列
age = c(25, 30, 28), # 数值型列
score = c(85.5, 90.0, 78.5), # 数值型列
passed = c(TRUE, TRUE, FALSE) # 逻辑型列
)
df
## name age score passed
## 1 张三 25 85.5 TRUE
## 2 李四 30 90.0 TRUE
## 3 王五 28 78.5 FALSE
# str():查看数据框结构
str(df)
## 'data.frame': 3 obs. of 4 variables:
## $ name : chr "张三" "李四" "王五"
## $ age : num 25 30 28
## $ score : num 85.5 90 78.5
## $ passed: logi TRUE TRUE FALSE
df <- data.frame(
name = c("张三", "李四", "王五"),
age = c(25, 30, 28)
)
# colnames():获取列名
colnames(df)
## [1] "name" "age"
# rownames():获取行名(默认是行号)
rownames(df)
## [1] "1" "2" "3"
# 修改列名和行名
colnames(df) <- c("姓名", "年龄")
rownames(df) <- c("学生A", "学生B", "学生C")
df
## 姓名 年龄
## 学生A 张三 25
## 学生B 李四 30
## 学生C 王五 28
# names() 也可以获取列名
names(df)
## [1] "姓名" "年龄"
df <- data.frame(
name = c("张三", "李四", "王五"),
age = c(25, 30, 28),
score = c(85, 90, 78)
)
# 使用 $ 获取列(返回向量)
df$name
## [1] "张三" "李四" "王五"
# 使用 [行, 列] 获取列
df[, "age"]
## [1] 25 30 28
# 获取第1行(所有列)
df[1, ]
## name age score
## 1 张三 25 85
# 获取第1行第2列的元素
df[1, 2]
## [1] 25
# 条件筛选:分数大于80的学生
df[df$score > 80, ]
## name age score
## 1 张三 25 85
## 2 李四 30 90
# subset():更简洁的筛选方式
subset(df, score > 80)
## name age score
## 1 张三 25 85
## 2 李四 30 90
# 多条件筛选
subset(df, age > 26 & score > 80)
## name age score
## 2 李四 30 90
df <- data.frame(
name = c("张三", "李四", "王五", "赵六"),
age = c(25, 30, 28, 35),
score = c(85, 90, 78, 88)
)
# head():查看前几行(默认6行)
head(df, 2)
## name age score
## 1 张三 25 85
## 2 李四 30 90
# tail():查看后几行
tail(df, 2)
## name age score
## 3 王五 28 78
## 4 赵六 35 88
# summary():查看统计摘要
summary(df)
## name age score
## Length:4 Min. :25.00 Min. :78.00
## Class :character 1st Qu.:27.25 1st Qu.:83.25
## Mode :character Median :29.00 Median :86.50
## Mean :29.50 Mean :85.25
## 3rd Qu.:31.25 3rd Qu.:88.50
## Max. :35.00 Max. :90.00
# dim():查看维度(行数,列数)
dim(df)
## [1] 4 3
# nrow():查看行数
nrow(df)
## [1] 4
# ncol():查看列数
ncol(df)
## [1] 3
df <- data.frame(
name = c("张三", "李四"),
age = c(25, 30)
)
# as.list():将数据框转换为列表
# 每列变成列表的一个元素
as.list(df)
## $name
## [1] "张三" "李四"
##
## $age
## [1] 25 30
split(df$name, df$age)
## $`25`
## [1] "张三"
##
## $`30`
## [1] "李四"
NA表示”缺失值”或”数据不可用”:
# 创建包含缺失值的向量
x <- c(1, 2, NA, 4, 5)
# is.na():检测是否为NA,返回逻辑向量
is.na(x)
## [1] FALSE FALSE TRUE FALSE FALSE
# 统计缺失值的数量
sum(is.na(x))
## [1] 1
# 含NA的运算结果也是NA
mean(x)
## [1] NA
# na.rm = TRUE:计算时忽略NA
mean(x, na.rm = TRUE)
## [1] 3
# 将NA替换为0
x[is.na(x)] <- 0
x
## [1] 1 2 0 4 5
# na.omit():删除包含NA的行
na.omit(c(1, 2, NA, 4))
## [1] 1 2 4
## attr(,"na.action")
## [1] 3
## attr(,"class")
## [1] "omit"
NULL表示”空”或”不存在”:
# NULL 是空对象
x <- NULL
# is.null():检测是否为NULL
is.null(x)
## [1] TRUE
# NULL 的长度为0
length(NULL)
## [1] 0
# NA 的长度为1
length(NA)
## [1] 1
# NULL 在向量中会被忽略
c(1, 2, NULL, 4)
## [1] 1 2 4
# NA 在向量中会保留
c(1, 2, NA, 4)
## [1] 1 2 NA 4
# NaN:Not a Number,非数值
# 0除以0的结果
0 / 0
## [1] NaN
# is.nan():检测是否为NaN
is.nan(0/0)
## [1] TRUE
# Inf:正无穷
# 1除以0的结果
1 / 0
## [1] Inf
# -Inf:负无穷
-1 / 0
## [1] -Inf
# is.infinite():检测是否为无穷
is.infinite(1/0)
## [1] TRUE
# is.finite():检测是否为有限数
is.finite(1)
## [1] TRUE
特殊值总结:
| 特殊值 | 含义 | 检测函数 |
|---|---|---|
NA |
缺失值 | is.na() |
NULL |
空对象 | is.null() |
NaN |
非数值 | is.nan() |
Inf |
正无穷 | is.infinite() |
-Inf |
负无穷 | is.infinite() |
# 创建分数向量
scores <- c(85, 90, 78, 92, 88, 76, 95, 82)
# sum():求和
sum(scores)
## [1] 686
# mean():计算平均值
mean(scores)
## [1] 85.75
# median():计算中位数
median(scores)
## [1] 86.5
# sd():计算标准差
sd(scores)
## [1] 6.734771
# var():计算方差
var(scores)
## [1] 45.35714
# min():最小值
min(scores)
## [1] 76
# max():最大值
max(scores)
## [1] 95
# range():范围(最小值和最大值)
range(scores)
## [1] 76 95
# quantile():计算分位数(默认四分位数)
quantile(scores)
## 0% 25% 50% 75% 100%
## 76.0 81.0 86.5 90.5 95.0
# 计算指定的分位数
quantile(scores, probs = c(0.1, 0.9))
## 10% 90%
## 77.4 92.9
| 函数 | 功能 | 示例结果 |
|---|---|---|
sum() |
求和 | 686 |
mean() |
平均值 | 85.75 |
median() |
中位数 | 86.5 |
sd() |
标准差 | 6.69 |
var() |
方差 | 44.79 |
min() |
最小值 | 76 |
max() |
最大值 | 95 |
range() |
范围 | 76, 95 |
quantile() |
分位数 | 多个百分位点 |
x <- c(3, 1, 4, 1, 5, 9, 2, 6)
# sort():直接返回排序后的向量
sort(x)
## [1] 1 1 2 3 4 5 6 9
# decreasing = TRUE:降序排列
sort(x, decreasing = TRUE)
## [1] 9 6 5 4 3 2 1 1
# order():返回排序后的索引位置
# 结果表示:第2个元素最小,第4个元素第二小...
order(x)
## [1] 2 4 7 1 3 5 8 6
# 使用order()对向量排序
x[order(x)]
## [1] 1 1 2 3 4 5 6 9
# rank():返回每个元素的排名
rank(x)
## [1] 4.0 1.5 5.0 1.5 6.0 8.0 3.0 7.0
# ties.method:处理相同值的方式
# "min":相同值取最小排名
rank(x, ties.method = "min")
## [1] 4 1 5 1 6 8 3 7
| 函数 | 返回值 | 用途 |
|---|---|---|
sort() |
排序后的向量 | 直接获取排序结果 |
order() |
排序后的索引位置 | 用于对其他相关向量排序 |
rank() |
每个元素的排名 | 获取排名信息 |
# 创建数据框
df <- data.frame(
name = c("张三", "李四", "王五"),
score = c(85, 92, 78)
)
# 按分数降序排列数据框
# order(df$score, decreasing = TRUE) 返回排序后的行号
df[order(df$score, decreasing = TRUE), ]
## name score
## 2 李四 92
## 1 张三 85
## 3 王五 78
# 创建有重复值的向量
x <- c(1, 2, 2, 3, 3, 3, 4, 4, 4, 4)
# unique():返回唯一值(去重后的向量)
unique(x)
## [1] 1 2 3 4
# duplicated():返回逻辑向量,标记是否为重复值
# 第一次出现为FALSE,后续重复为TRUE
duplicated(x)
## [1] FALSE FALSE TRUE FALSE TRUE TRUE FALSE TRUE TRUE TRUE
# 使用逻辑取反获取唯一值
x[!duplicated(x)]
## [1] 1 2 3 4
# 统计唯一值的个数
length(unique(x))
## [1] 4
# 定义两个集合
A <- c(1, 2, 3, 4, 5)
B <- c(4, 5, 6, 7, 8)
# union():并集(A和B的所有元素,去重)
union(A, B)
## [1] 1 2 3 4 5 6 7 8
# intersect():交集(A和B的共同元素)
intersect(A, B)
## [1] 4 5
# setdiff():差集(A有但B没有的元素)
setdiff(A, B)
## [1] 1 2 3
# setdiff(B, A):B有但A没有的元素
setdiff(B, A)
## [1] 6 7 8
# %in%:判断元素是否在集合中
3 %in% A
## [1] TRUE
10 %in% A
## [1] FALSE
# 可以判断多个元素
c(1, 3, 10) %in% A
## [1] TRUE TRUE FALSE
# setequal():判断两个集合是否相等(不考虑顺序)
setequal(c(1, 2, 3), c(3, 2, 1))
## [1] TRUE
| 函数/运算符 | 功能 | 示例 |
|---|---|---|
union() |
并集 | A和B的所有元素 |
intersect() |
交集 | A和B的共同元素 |
setdiff() |
差集 | A有但B没有的元素 |
%in% |
成员判断 | 元素是否在集合中 |
setequal() |
集合相等判断 | 两个集合是否相同 |
name <- "张三"
# paste():连接字符串,默认用空格分隔
paste("姓名:", name)
## [1] "姓名: 张三"
# paste():使用自定义分隔符
paste("A", "B", "C", sep = "-")
## [1] "A-B-C"
# paste0():连接字符串,无分隔符
paste0("Hello", "World")
## [1] "HelloWorld"
# paste():将向量元素连接成一个字符串
paste(c("A", "B", "C"), collapse = ", ")
## [1] "A, B, C"
# strsplit():按指定分隔符拆分字符串
sentence <- "苹果,香蕉,橙子"
strsplit(sentence, ",")
## [[1]]
## [1] "苹果" "香蕉" "橙子"
# sub():替换第一个匹配项
text <- "Hello World"
sub("World", "R", text)
## [1] "Hello R"
# gsub():替换所有匹配项
text2 <- "apple apple apple"
gsub("apple", "orange", text2)
## [1] "orange orange orange"
# toupper():转大写
toupper("hello")
## [1] "HELLO"
# tolower():转小写
tolower("HELLO")
## [1] "hello"
# nchar():统计字符数
nchar("你好世界")
## [1] 4
# substr():提取子字符串(从第1个到第5个字符)
substr("Hello World", 1, 5)
## [1] "Hello"
# trimws():去除首尾空格
trimws(" Hello World ")
## [1] "Hello World"
| 函数 | 功能 | 示例 |
|---|---|---|
paste() |
连接字符串(可指定分隔符) | paste("A", "B") → “A B” |
paste0() |
连接字符串(无分隔符) | paste0("A", "B") → “AB” |
strsplit() |
分割字符串 | 按指定字符拆分 |
sub() |
替换第一个匹配 | 只替换第一个 |
gsub() |
替换所有匹配 | 替换所有匹配项 |
toupper() |
转大写 | “hello” → “HELLO” |
tolower() |
转小写 | “HELLO” → “hello” |
nchar() |
字符数 | 统计字符个数 |
substr() |
提取子串 | 按位置截取 |
trimws() |
去除首尾空格 | 清理空白字符 |
# as.numeric():转换为数值型
as.numeric("123")
## [1] 123
# as.character():转换为字符型
as.character(123)
## [1] "123"
# as.logical():转换为逻辑型
# 非零为TRUE,零为FALSE
as.logical(1)
## [1] TRUE
as.logical(0)
## [1] FALSE
# as.factor():转换为因子
as.factor(c("A", "B", "A"))
## [1] A B A
## Levels: A B
# as.Date():转换为日期
as.Date("2024-01-15")
## [1] "2024-01-15"
# as.vector():转换为向量
as.vector(matrix(1:4, nrow = 2))
## [1] 1 2 3 4
# as.data.frame():转换为数据框
as.data.frame(matrix(1:6, nrow = 2))
## V1 V2 V3
## 1 1 3 5
## 2 2 4 6
# as.list():转换为列表
as.list(c(1, 2, 3))
## [[1]]
## [1] 1
##
## [[2]]
## [1] 2
##
## [[3]]
## [1] 3
# is.numeric():判断是否为数值型
is.numeric(123)
## [1] TRUE
# is.character():判断是否为字符型
is.character("hello")
## [1] TRUE
# is.logical():判断是否为逻辑型
is.logical(TRUE)
## [1] TRUE
# is.factor():判断是否为因子
is.factor(factor(c("A", "B")))
## [1] TRUE
# is.vector():判断是否为向量
is.vector(c(1, 2, 3))
## [1] TRUE
# is.data.frame():判断是否为数据框
is.data.frame(data.frame(x = 1))
## [1] TRUE
# is.list():判断是否为列表
is.list(list(a = 1))
## [1] TRUE
向量化运算是R语言的核心特性之一。它的意思是:对整个向量进行操作,而不需要写循环。
假设要计算向量中每个元素的平方:
# 创建向量
x <- 1:5
# 向量化方式:直接对向量进行运算
# R会自动对每个元素求平方
x^2
## [1] 1 4 9 16 25
# 传统循环方式:需要显式写循环
# 先创建一个空向量存储结果
result <- numeric(5)
# 循环计算每个元素的平方
for (i in 1:5) {
result[i] <- x[i]^2
}
result
## [1] 1 4 9 16 25
向量化运算的优势: 1. 代码简洁:一行代码完成 2. 执行效率高:R内部用C语言优化 3. 易于阅读:意图清晰明了
ifelse() 是向量化版的 if-else:
# 创建分数向量
scores <- c(85, 60, 72, 45, 90)
# ifelse(条件, 条件为TRUE时的值, 条件为FALSE时的值)
# 对每个元素判断:>=60为"及格",否则为"不及格"
ifelse(scores >= 60, "及格", "不及格")
## [1] "及格" "及格" "及格" "不及格" "及格"
# 嵌套ifelse实现多条件判断
# >=90为"优秀",>=60为"及格",否则为"不及格"
ifelse(scores >= 90, "优秀",
ifelse(scores >= 60, "及格", "不及格"))
## [1] "及格" "及格" "及格" "不及格" "优秀"
apply系列函数用于替代循环,对数据的行、列或列表元素进行操作。
apply() 用于矩阵或数据框,按行或列应用函数:
# 创建矩阵
m <- matrix(1:12, nrow = 3)
m
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 2 5 8 11
## [3,] 3 6 9 12
# apply(数据, 维度, 函数)
# 维度:1=按行,2=按列
# 按行求和(对每一行应用sum函数)
apply(m, 1, sum)
## [1] 22 26 30
# 按列求和(对每一列应用sum函数)
apply(m, 2, sum)
## [1] 6 15 24 33
# 按行计算平均值
apply(m, 1, mean)
## [1] 5.5 6.5 7.5
# 使用匿名函数:将每列元素乘以2
apply(m, 2, function(x) x * 2)
## [,1] [,2] [,3] [,4]
## [1,] 2 8 14 20
## [2,] 4 10 16 22
## [3,] 6 12 18 24
参数说明: - 第1个参数:数据(矩阵或数据框) - 第2个参数:维度(1=行,2=列) - 第3个参数:要应用的函数
lapply() 用于列表或向量,返回列表:
# 创建列表
my_list <- list(
a = c(1, 2, 3),
b = c(10, 20, 30, 40),
c = c(100, 200)
)
# lapply(列表, 函数):对每个元素应用函数
# 计算每个元素的平均值
lapply(my_list, mean)
## $a
## [1] 2
##
## $b
## [1] 25
##
## $c
## [1] 150
# 计算每个元素的和
lapply(my_list, sum)
## $a
## [1] 6
##
## $b
## [1] 100
##
## $c
## [1] 300
sapply() 是 lapply()
的简化版,返回向量或矩阵:
my_list <- list(
a = c(1, 2, 3),
b = c(10, 20, 30, 40),
c = c(100, 200)
)
# sapply() 返回向量(比lapply更简洁)
sapply(my_list, mean)
## a b c
## 2 25 150
# 计算每个元素的长度
sapply(my_list, length)
## a b c
## 3 4 2
vapply() 类似
sapply(),但需要指定返回值类型,更安全:
my_list <- list(a = 1:3, b = 4:6)
# vapply(列表, 函数, 返回值类型模板)
# numeric(1) 表示返回单个数值
vapply(my_list, mean, numeric(1))
## a b
## 2 5
tapply() 按分组应用函数:
# 创建分数和对应的班级
scores <- c(85, 90, 78, 92, 88, 76)
classes <- c("A", "A", "B", "B", "A", "B")
# tapply(数据, 分组变量, 函数)
# 按班级计算平均分
tapply(scores, classes, mean)
## A B
## 87.66667 82.00000
mapply() 是多变量版本的 sapply():
# mapply(函数, 向量1, 向量2, ...)
# 将两个向量的对应元素相加
mapply(function(x, y) x + y,
c(1, 2, 3),
c(10, 20, 30))
## [1] 11 22 33
# 重复字符:A重复1次,B重复2次,C重复3次
mapply(rep, times = 1:3, x = c("A", "B", "C"))
## [[1]]
## [1] "A"
##
## [[2]]
## [1] "B" "B"
##
## [[3]]
## [1] "C" "C" "C"
replicate() 用于重复执行某个操作:
# 重复3次计算1:10的平均值
replicate(3, mean(1:10))
## [1] 5.5 5.5 5.5
# 设置随机种子,保证结果可重复
set.seed(123)
# 重复5次:生成10个正态随机数并计算平均值
replicate(5, mean(rnorm(10)))
## [1] 0.074625644 0.208621961 -0.424558873 0.322044550 -0.008715537
x <- 10
# if (条件) { 执行代码 }
# 条件为TRUE时执行花括号内的代码
if (x > 5) {
print("x大于5")
}
## [1] "x大于5"
score <- 75
# if-else:二选一
# 条件为TRUE执行if块,否则执行else块
if (score >= 60) {
print("及格")
} else {
print("不及格")
}
## [1] "及格"
score <- 85
# if-else if-else:多条件判断
# 从上到下依次判断,遇到第一个TRUE的条件就执行对应代码块
if (score >= 90) {
print("优秀")
} else if (score >= 80) {
print("良好")
} else if (score >= 60) {
print("及格")
} else {
print("不及格")
}
## [1] "良好"
day <- "周一"
# switch(判断值, 情况1=结果1, 情况2=结果2, ..., 默认结果)
# 根据day的值返回对应的活动
activity <- switch(day,
"周一" = "开会",
"周二" = "培训",
"周三" = "调研",
"周四" = "写作",
"周五" = "总结",
"周末" # 默认值(没有匹配时返回)
)
activity
## [1] "开会"
# switch也可以使用数字索引
num <- 2
# 返回第2个值:"第二"
switch(num, "第一", "第二", "第三")
## [1] "第二"
遍历向量:
# for (变量 in 序列) { 执行代码 }
# 变量依次取序列中的每个值
for (i in 1:5) {
print(i)
}
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
遍历字符向量:
fruits <- c("苹果", "香蕉", "橙子")
# fruit依次取向量中的每个元素
for (fruit in fruits) {
print(paste("我喜欢", fruit))
}
## [1] "我喜欢 苹果"
## [1] "我喜欢 香蕉"
## [1] "我喜欢 橙子"
遍历列表:
my_list <- list(a = 1:3, b = 4:6)
# names()获取列表的元素名称
for (name in names(my_list)) {
print(paste(name, "的均值是", mean(my_list[[name]])))
}
## [1] "a 的均值是 2"
## [1] "b 的均值是 5"
遍历数据框:
df <- data.frame(name = c("张三", "李四"), score = c(85, 90))
# nrow()获取行数,逐行遍历
for (i in 1:nrow(df)) {
print(paste(df$name[i], "的分数是", df$score[i]))
}
## [1] "张三 的分数是 85"
## [1] "李四 的分数是 90"
# while (条件) { 执行代码 }
# 条件为TRUE时重复执行,直到条件为FALSE
count <- 1
while (count <= 5) {
print(count)
count <- count + 1 # 更新计数器,否则会无限循环
}
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
repeat循环(无限循环,必须用break退出):
count <- 1
# repeat会无限循环,直到遇到break
repeat {
print(count)
count <- count + 1
# 当count > 5时退出循环
if (count > 5) {
break
}
}
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
break:跳出整个循环
# 当i等于5时,跳出循环
for (i in 1:10) {
if (i == 5) {
break # 跳出循环,不再继续
}
print(i)
}
## [1] 1
## [1] 2
## [1] 3
## [1] 4
next:跳过当前迭代,继续下一次
# 当i等于3时,跳过本次循环,继续下一次
for (i in 1:5) {
if (i == 3) {
next # 跳过本次,继续i=4
}
print(i)
}
## [1] 1
## [1] 2
## [1] 4
## [1] 5
在R中,很多循环可以用向量化操作替代,效率更高:
x <- 1:1000000
# 向量化方式:直接对向量运算(推荐)
# 简洁且高效
y <- x^2
# 循环方式:需要显式写循环(不推荐)
# 代码冗长且效率低
y <- numeric(length(x))
for (i in seq_along(x)) {
y[i] <- x[i]^2
}
原则:能用向量化就用向量化,必要时用apply系列函数,最后才考虑显式循环。
使用 function() 创建函数:
# 定义函数:function(参数) { 函数体 }
# greet 是函数名,name 是参数
greet <- function(name) {
result <- paste("你好,", name)
return(result) # return() 返回结果
}
# 调用函数
greet("张三")
## [1] "你好, 张三"
# 定义函数:a和b是形式参数(形参)
add <- function(a, b) {
return(a + b)
}
# 调用函数:3和5是实际参数(实参)
# 按位置传递参数
add(3, 5)
## [1] 8
# 按名称传递参数
add(a = 3, b = 5)
## [1] 8
# 按名称传递时,顺序可以改变
add(b = 5, a = 3)
## [1] 8
# greeting = "你好" 设置默认值
# 调用时不传该参数,就使用默认值
greet <- function(name, greeting = "你好") {
paste(greeting, name)
}
# 使用默认值
greet("张三")
## [1] "你好 张三"
# 覆盖默认值
greet("张三", "早上好")
## [1] "早上好 张三"
# 使用 return() 显式返回
add <- function(a, b) {
return(a + b)
}
add(1, 2)
## [1] 3
# 隐式返回:最后一行表达式的值就是返回值
add2 <- function(a, b) {
a + b # 没有return,最后一行自动返回
}
add2(1, 2)
## [1] 3
# 返回多个值:使用列表
multi_return <- function(x) {
list(
original = x, # 原始值
squared = x^2, # 平方
cubed = x^3 # 立方
)
}
multi_return(3)
## $original
## [1] 3
##
## $squared
## [1] 9
##
## $cubed
## [1] 27
# 全局变量
x <- 10
my_func <- function() {
# 局部变量:只在函数内部有效
x <- 20
print(paste("函数内 x =", x))
}
my_func()
## [1] "函数内 x = 20"
# 函数外部的x不受影响
print(paste("函数外 x =", x))
## [1] "函数外 x = 10"
# 函数可以读取全局变量
y <- 10
my_func2 <- function() {
# 函数内没有定义y,所以使用全局变量y
print(paste("y =", y))
}
my_func2()
## [1] "y = 10"
作用域规则: 1.
函数内部创建的变量是局部变量,只在函数内有效 2.
函数可以访问外部(全局)变量,但不能直接修改 3.
如需在函数内修改全局变量,使用 <<- 运算符
x <- 10
modify_global <- function() {
# <<- 超赋值运算符:修改全局变量
x <<- 20
}
modify_global()
# x已被修改为20
x
## [1] 20
在R中,函数也是对象,可以作为参数传递:
# 定义一个接受函数作为参数的函数
apply_function <- function(x, func) {
func(x) # 调用传入的函数
}
# 传入mean函数
apply_function(c(1, 2, 3, 4, 5), mean)
## [1] 3
# 传入sum函数
apply_function(c(1, 2, 3, 4, 5), sum)
## [1] 15
没有名字的函数,通常用于一次性操作:
# 匿名函数:没有函数名,直接定义在调用处
# function(x) x^2 就是匿名函数
sapply(1:5, function(x) x^2)
## [1] 1 4 9 16 25
# 另一个例子:将字符转为大写并添加感叹号
sapply(c("a", "b", "c"), function(x) paste(toupper(x), "!"))
## a b c
## "A !" "B !" "C !"
函数可以”记住”创建时的环境:
# 闭包:函数返回另一个函数
# 内部函数可以访问外部函数的变量
counter <- function() {
count <- 0 # 这个变量会被内部函数"记住"
function() {
count <<- count + 1 # 使用 <<- 修改外部函数的变量
count
}
}
# 创建一个计数器
my_counter <- counter()
# 每次调用计数器,count都会增加
my_counter() # 1
## [1] 1
my_counter() # 2
## [1] 2
my_counter() # 3
## [1] 3
... 允许函数接受任意数量的参数:
# ... 表示可以接受任意数量的参数
my_sum <- function(...) {
# list(...) 将所有参数转换为列表
args <- list(...)
# unlist() 将列表展开为向量,然后求和
sum(unlist(args))
}
# 可以传入任意数量的参数
my_sum(1, 2, 3, 4, 5)
## [1] 15
# 另一个例子:拼接字符串
my_cat <- function(prefix, ...) {
args <- list(...)
paste(prefix, paste(args, collapse = " "))
}
my_cat("结果:", "A", "B", "C")
## [1] "结果: A B C"
# read.table():读取通用文本文件
# file:文件路径
# header:第一行是否为列名
# sep:分隔符(\t表示制表符)
df <- read.table("data.txt", header = TRUE, sep = "\t")
# read.csv():读取CSV文件(逗号分隔)
# 默认header=TRUE
df <- read.csv("data.csv")
# stringsAsFactors = FALSE:不将字符转为因子
df <- read.csv("data.csv", header = TRUE, stringsAsFactors = FALSE)
# read.delim():读取制表符分隔的文件
# 默认sep="\t"
df <- read.delim("data.txt")
# 从剪贴板读取数据(先复制Excel中的数据)
# "clipboard" 表示从剪贴板读取
df <- read.table("clipboard", header = TRUE)
使用 readxl 包:
# 需要先安装并加载readxl包
library(readxl)
# 读取Excel文件
df <- read_excel("data.xlsx")
# 指定工作表名称
df <- read_excel("data.xlsx", sheet = "Sheet1")
# 指定工作表序号
df <- read_excel("data.xlsx", sheet = 2)
# write.table():写入文本文件
# sep:分隔符
# row.names = FALSE:不写入行名
write.table(df, "output.txt", sep = "\t", row.names = FALSE)
# write.csv():写入CSV文件
write.csv(df, "output.csv", row.names = FALSE)
保存和加载R对象:
x <- 1:10
y <- c("a", "b", "c")
# save():保存多个R对象到.RData文件
save(x, y, file = "my_data.RData")
# load():加载.RData文件
load("my_data.RData")
# save.image():保存整个工作空间
save.image("workspace.RData")
# 加载工作空间
load("workspace.RData")
保存和加载单个R对象:
my_data <- data.frame(x = 1:10, y = letters[1:10])
# saveRDS():保存单个对象到.rds文件
# 与save()的区别:加载时可以赋值给任意变量名
saveRDS(my_data, "my_data.rds")
# readRDS():读取.rds文件
loaded_data <- readRDS("my_data.rds")
# scan():从键盘读取数据
# 默认读取数值,按Enter结束
numbers <- scan()
# what = "character":读取字符
words <- scan(what = "character")
# readline():读取一行文本
# prompt:提示信息
name <- readline(prompt = "请输入你的名字: ")
x <- 10
# print():打印对象
print(x)
## [1] 10
# cat():连接并输出
# "\n" 表示换行
cat("数值是:", x, "\n")
## 数值是: 10
# message():输出消息(用于提示信息)
message("这是一条消息")
## 这是一条消息
# warning():输出警告
warning("这是一个警告")
## Warning: 这是一个警告
R包是R函数、数据和文档的集合。可以把R包理解为”扩展模块”,安装后可以获得额外的功能。
# install.packages():从CRAN安装包
install.packages("ggplot2")
# 同时安装多个包
install.packages(c("dplyr", "tidyr", "ggplot2"))
# Bioconductor是生物信息学专用仓库
# 需要先安装BiocManager
if (!require("BiocManager")) {
install.packages("BiocManager")
}
# 使用BiocManager安装Bioconductor包
BiocManager::install("DESeq2")
# 需要先安装devtools包
install.packages("devtools")
# 从GitHub安装
devtools::install_github("用户名/包名")
# library():加载包(推荐)
library(ggplot2)
library(dplyr)
# require():加载包,返回TRUE/FALSE
require(tidyr)
# 智能加载:如果包不存在则先安装
if (!require(some_package)) {
install.packages("some_package")
library(some_package)
}
# installed.packages():查看所有已安装包的详细信息
installed.packages()
# library():不带参数,打开包列表窗口
library()
# search():查看当前已加载的包
search()
# update.packages():更新所有包
update.packages()
# 更新指定包
update.packages("ggplot2")
# remove.packages():卸载包
remove.packages("old_package")
# library(help = 包名):查看包的帮助文档
library(help = ggplot2)
# vignette():查看包的教程文档
vignette("ggplot2")
# 查看所有可用的vignette
vignette()
# 在浏览器中打开vignette
browseVignettes("ggplot2")
# ?函数名:查看函数帮助
?mean
# help(函数名):等价于 ?函数名
help(mean)
# 查看运算符帮助(需要用反引号包裹)
?`+`
help("+")
# help.search():搜索帮助文档
help.search("regression")
# ??关键词:等价于 help.search()
??regression
# apropos():搜索包含指定字符串的函数名
apropos("mean")
# example():运行函数的示例代码
example(mean)
# 运行ggplot包的示例
example(ggplot)
# save.image():保存整个工作空间到文件
save.image("my_workspace.RData")
# load():加载工作空间
load("my_workspace.RData")
# save():保存指定的变量
save(list = c("x", "y"), file = "selected.RData")
# history():查看命令历史
history()
# 查看最近50条命令
history(50)
# savehistory():保存命令历史
savehistory("my_history.Rhistory")
# loadhistory():加载命令历史
loadhistory("my_history.Rhistory")
# 定义嵌套函数
f <- function(x) g(x)
g <- function(x) h(x)
h <- function(x) stop("出错了!")
# 调用函数会报错
f(1)
# traceback():显示错误发生时的调用栈
traceback()
# debug():进入函数调试模式
debug(mean)
mean(1:10)
# undebug():退出调试模式
undebug(mean)
# browser():在代码中设置断点
my_func <- function(x) {
y <- x + 1
browser() # 程序会在这里暂停,可以检查变量
z <- y * 2
return(z)
}
my_func(5)
| 快捷键 | 功能 |
|---|---|
Ctrl + Enter |
运行当前行或选中代码 |
Ctrl + Shift + Enter |
运行整个脚本 |
Ctrl + L |
清空控制台 |
Ctrl + S |
保存文件 |
Ctrl + Shift + C |
注释/取消注释 |
Ctrl + D |
删除整行 |
Ctrl + Shift + K |
编译R Markdown |
Tab |
代码自动补全 |
Ctrl + Space |
触发自动补全 |
Ctrl + 1 |
切换到脚本编辑器 |
Ctrl + 2 |
切换到控制台 |
Ctrl + Shift + N |
新建R脚本 |
Ctrl + O |
打开文件 |
Ctrl + W |
关闭当前文件 |
本节课涵盖了以下核心内容: