R 语言入门:数据结构、向量化与函数
R 是统计计算与数据可视化的首选语言。本文讲解 R 的核心:五种数据结构、向量化运算思维、控制流与函数,为后续 tidyverse 与 ggplot2 打下基础。
1. 环境准备
1.1 安装与 IDE
1.2 基本操作
# 赋值:<- 是 R 的经典赋值符(= 也可用)
x <- 10
x
# 查看帮助
?mean
help("lm")
2. 基础数据结构
R 的核心数据结构按维度与同质性划分:
| 结构 | 维度 | 元素类型 |
|---|---|---|
| vector(向量) | 1 | 同质 |
| factor(因子) | 1 | 分类 |
| matrix(矩阵) | 2 | 同质 |
| data.frame(数据框) | 2 | 可异质 |
| list(列表) | N | 可异质 |
2.1 向量(vector)
# 创建向量
a <- c(1, 2, 3, 4, 5) # combine
b <- 1:10 # 序列
c <- seq(0, 1, by = 0.2) # 步长序列
d <- rep("A", 3) # 重复
e <- sample(1:100, 10) # 随机抽样
# 类型
typeof(a) # "double"
is.numeric(a) # TRUE
# 索引(R 从 1 开始!)
a[1] # 1
a[c(1, 3)] # 第 1、3 个元素
a[-2] # 删除第 2 个
a[a > 3] # 条件筛选
names(a) <- c("x1", "x2", "x3", "x4", "x5")
a["x1"] # 按名字取
R 的索引从 1 开始,这是与 Python 最大的习惯差异。
2.2 因子(factor)
treatment <- factor(c("control", "drug", "control", "drug"),
levels = c("control", "drug"))
levels(treatment) # "control" "drug"
table(treatment) # 频数统计
2.3 矩阵(matrix)
m <- matrix(1:12, nrow = 3, ncol = 4)
# [,1] [,2] [,3] [,4]
# [1,] 1 4 7 10
# [2,] 2 5 8 11
# [3,] 3 6 9 12
m[2, 3] # 第 2 行第 3 列:8
m[1, ] # 第 1 行
m[, 2] # 第 2 列
t(m) # 转置
m %*% t(m) # 矩阵乘法
2.4 数据框(data.frame)
数据框是表格数据的核心结构:
df <- data.frame(
gene = c("TP53", "BRCA1", "EGFR"),
expression = c(12.3, 8.9, 45.1),
chromosome = c(17, 17, 7)
)
# 查看结构
str(df)
summary(df)
# 取列
df$expression # $ 运算符
df[["expression"]]
df[, "expression"]
# 取行
df[1, ] # 第一行
df[df$expression > 10, ]
# 增加列
df$log2fc <- log2(df$expression)
2.5 列表(list)
列表可容纳任意类型:
result <- list(
name = "分析结果",
pvalue = 0.003,
coef = c(1.2, -0.5, 3.1),
model = lm(expression ~ chromosome, data = df)
)
result$pvalue
result[[3]] # 数值向量
3. 向量化运算
R 的核心思想:对整个向量运算,而非逐元素循环。
x <- c(1, 2, 3, 4, 5)
x * 2 # 逐元素乘
x + 10
sqrt(x)
log2(x)
# 向量与向量
y <- c(5, 4, 3, 2, 1)
x + y # 对应位置相加
# 比较运算返回逻辑向量
x > 3 # FALSE FALSE FALSE TRUE TRUE
# 统计函数
sum(x); mean(x); median(x); sd(x); range(x)
4. 控制流
4.1 条件
score <- 85
if (score >= 90) {
grade <- "A"
} else if (score >= 80) {
grade <- "B"
} else {
grade <- "C"
}
print(grade)
# 向量化条件:ifelse
values <- c(60, 90, 45, 75)
result <- ifelse(values >= 60, "pass", "fail")
print(result) # "pass" "pass" "fail" "pass"
4.2 循环
# for 循环
for (i in 1:5) {
print(i ^ 2)
}
# 遍历向量元素
genes <- c("TP53", "BRCA1", "EGFR")
for (g in genes) {
print(paste("分析", g))
}
# while 循环
n <- 0
while (n < 5) {
n <- n + 1
}
4.3 尽量避免循环:apply 家族
R 中常用 apply 家族替代显式循环:
m <- matrix(1:12, nrow = 3)
apply(m, 1, mean) # 对每行求均值
apply(m, 2, sum) # 对每列求和
lapply(list(1:3, 4:6), mean) # 对列表每个元素操作,返回列表
sapply(list(1:3, 4:6), mean) # 简化版,返回向量
5. 函数
5.1 定义函数
gc_content <- function(seq) {
seq <- toupper(seq)
gc <- sum(strsplit(seq, "")[[1]] %in% c("G", "C"))
gc / nchar(seq) * 100
}
gc_content("ATGCCGA")
# [1] 57.14286
5.2 默认参数与返回值
normalize <- function(x, method = "zscore") {
if (method == "zscore") {
(x - mean(x)) / sd(x)
} else if (method == "minmax") {
(x - min(x)) / (max(x) - min(x))
} else {
stop("未知方法: ", method)
}
}
normalize(c(1, 2, 3, 4, 5))
normalize(c(1, 2, 3, 4, 5), method = "minmax")
5.3 匿名函数与函数式编程
# 匿名函数
sapply(1:5, function(i) i ^ 2)
# purrr 风格的 map(需要 tidyverse,下一篇详述)
# purrr::map_dbl(1:5, ~ .x ^ 2)
6. 实用技巧
# 管道(R 4.1+ 原生管道 |>/ 或 magrittr %>%)
x <- c(1, 2, 3, 4, 5)
x |> mean() |> round(2)
# 缺失值处理
x <- c(1, NA, 3, NA)
is.na(x)
sum(is.na(x))
x[!is.na(x)]
na.omit(x)
# 合并数据框
df1 <- data.frame(id = 1:3, value = c("a", "b", "c"))
df2 <- data.frame(id = 2:4, score = c(90, 85, 88))
merged <- merge(df1, df2, by = "id") # 类似 SQL join
7. 小结
- 五种核心结构:向量 / 因子 / 矩阵 / 数据框 / 列表
- R 索引从 1 开始;
$取列;[ ]取行 - 向量化运算 +
ifelse+apply家族替代显式循环 - 函数:默认参数、
stop()报错、匿名函数
下一篇将介绍 tidyverse:用 dplyr 优雅地完成数据操作。