R 语言教程
什么是 R 语言?
R 是一种用于统计计算与数据可视化的开源编程语言,由 Ross Ihaka 和 Robert Gentleman 于 1995 年创建,现由 R 基金会维护。R 在数据分析、统计建模、机器学习与学术研究领域应用广泛。
R 语言的核心特点
- 统计强项:内置大量统计函数与概率分布
- 可视化:ggplot2 等绘图系统全球闻名
- 数据分析:数据框、矩阵等数据结构贴合数据分析场景
- 包生态:CRAN 上有 2 万+ 扩展包
- 免费开源:跨平台(Windows/macOS/Linux)
R 能做什么
- 数据清洗与统计分析
- 数据可视化(报表、仪表盘)
- 机器学习与预测建模
- 生物信息学、金融分析
- 学术研究中的统计检验
第一个 R 程序
# 交互式或脚本运行
print("Hello, R!")
# 基本运算
x <- 10
y <- 20
print(x + y) # 30
开发环境
RStudio: 最流行的 R IDE(免费)
R Console: 命令行交互
Jupyter: 通过 IRkernel 使用
VS Code: R 插件
R 环境安装
R 环境安装
安装 R 语言与 RStudio 是开始 R 开发的第一步。
1. 安装 R
# Windows
下载 https://cran.r-project.org/bin/windows/base/
双击安装,默认路径 C:\\Program Files\\R\\R-x.x.x
# macOS
下载 dmg 安装包安装
# Linux (Ubuntu)
sudo apt update
sudo apt install r-base
# 验证
R --version
2. 安装 RStudio(推荐 IDE)
下载 https://posit.co/download/rstudio-desktop/
安装后打开,自动识别已安装的 R
3. RStudio 界面
左上: 脚本编辑器(写代码)
左下: Console(交互执行)
右上: 环境/历史
右下: 文件/绘图/包/帮助
4. 安装扩展包
# 从 CRAN 安装
install.packages("ggplot2")
install.packages("dplyr")
# 从 Bioconductor 安装(生物信息)
if (!require("BiocManager", quietly = TRUE))
install.packages("BiocManager")
BiocManager::install("DESeq2")
# 加载包
library(ggplot2)
5. 第一个脚本
# hello.R
message("Hello, R!")
x <- 1:10
print(mean(x)) # 5.5
# 运行
Rscript hello.R
6. 常见问题
- 安装包慢:设置国内镜像(清华/中科大 CRAN 镜像)
- R 找不到:RStudio Tools → Global Options 指定路径
- 权限问题:Windows 避免装在需要管理员权限的目录
R 基础语法
R 基础语法
R 的语法简洁,以赋值、向量化计算为核心。
赋值
# 三种赋值方式(推荐 <-)
x <- 10
y = 20 # 也可用 =
10 -> z # 向右赋值
# 打印
print(x)
print(x + y + z)
注释
# 这是注释
# 用 # 号开头
print("R 中 # 用于注释")
变量命名
my_var <- 1 # 小写+下划线
myVar <- 2 # 驼峰
.隐藏变量 <- 3 # 点开头(隐藏)
# 不能以数字开头
# 区分大小写: Name 和 name 不同
向量(基本单位)
# c() 创建向量
v <- c(1, 2, 3, 4, 5)
print(v)
# 序列
s1 <- 1:10 # 1 到 10
s2 <- seq(1, 10, by = 2) # 1,3,5,7,9
s3 <- rep(3, 5) # 3,3,3,3,3
# 向量运算(自动逐元素)
a <- c(1, 2, 3)
b <- c(10, 20, 30)
print(a + b) # 11 22 33
print(a * 2) # 2 4 6
输出
print("简单输出")
cat("拼接", "输出", "文本\n") # cat 不自动换行
sprintf("格式化: %d", 42) # "格式化: 42"
基础函数
sum(1:10) # 55 求和
mean(c(1,2,3)) # 2 均值
median(c(1,2,3)) # 2 中位数
sd(c(1,2,3)) # 标准差
max(c(1,5,3)) # 5
min(c(1,5,3)) # 1
length(c(1,2,3)) # 3 长度
R 注释
R 注释
注释帮助理解代码,R 支持单行注释与块注释技巧。
单行注释
# 这是单行注释
x <- 5 # 行尾注释也可
# 打印变量
print(x)
块注释技巧
# R 没有原生多行注释,但可用 if(FALSE) 包裹
if (FALSE) {
# 这段代码不会执行
# 相当于块注释
complicated_function()
}
注释的实践
# 1. 说明"为什么"而非"是什么"
# 将营收标准化到 0-1(避免量纲影响)
normalized <- (revenue - min(revenue)) /
(max(revenue) - min(revenue))
# 2. 标注 TODO
# TODO: 后续改为读取数据库
# 3. 引用来源
# 公式来源: ISLR 第 3 章,式(3.4)
Roxygen 文档注释(包开发)
# 开发 R 包时用 roxygen2 格式
#' 计算平均值
#'
#' @param x 数值向量
#' @return 平均值
#' @examples
#' mean2(c(1, 2, 3))
mean2 <- function(x) {
mean(x)
}
注释的注意事项
1. 不要注释明显的内容(x <- 5 # 赋值)
2. 更新代码时同步更新注释
3. 用注释分隔代码块(# ---- 数据加载 ----)
R 基础运算
R 基础运算
R 支持算术、比较、逻辑等运算符,并擅长向量化运算。
算术运算符
+ 加法 - 减法
* 乘法 / 除法
^ 幂 %% 取余
%/% 整除
10 / 3 # 3.333333
10 %/% 3 # 3
10 %% 3 # 1
2^10 # 1024
向量化运算
a <- c(1, 2, 3)
b <- c(4, 5, 6)
a + b # 5 7 9
a * b # 4 10 18
a^2 # 1 4 9
sqrt(c(1, 4, 9)) # 1 2 3
log(c(1, 10, 100)) # 对数
# 循环利用(长度不同时自动重复)
c(1, 2) + c(10, 20, 30, 40) # 11 22 31 42
比较运算符
== 等于 != 不等于
> 大于 < 小于
>= 大于等于 <= 小于等于
5 > 3 # TRUE
c(1, 2) == c(1, 3) # TRUE FALSE
逻辑运算符
& 元素级与
| 元素级或
! 非
&& 标量与(短路)
|| 标量或(短路)
x <- c(TRUE, FALSE, TRUE)
y <- c(TRUE, TRUE, FALSE)
x & y # TRUE FALSE FALSE
x | y # TRUE TRUE TRUE
!x # FALSE TRUE FALSE
# 元素级:返回向量;标量:只取第一个
TRUE && FALSE # FALSE
c(TRUE, TRUE) && c(FALSE, FALSE) # FALSE(只看第一个)
数学函数
abs(-5) # 5
round(3.14159, 2) # 3.14
floor(3.7) # 3
ceiling(3.2) # 4
exp(1) # 2.718282
pi # 3.141593
矩阵运算
m1 <- matrix(1:4, nrow = 2)
m2 <- matrix(5:8, nrow = 2)
m1 + m2 # 元素加法
m1 %*% m2 # 矩阵乘法
t(m1) # 转置
R 数据类型
R 数据类型
R 的基本数据类型包括数值、整数、复数、逻辑、字符与因子。
基本类型
# 数值型(默认 double)
num <- 3.14
class(num) # "numeric"
# 整数型(加 L)
int <- 42L
class(int) # "integer"
# 复数
com <- 2 + 3i
class(com) # "complex"
# 逻辑
logi <- TRUE
class(logi) # "logical"
# 字符
str <- "Hello"
class(str) # "character"
类型判断与转换
# 判断
is.numeric(3.14) # TRUE
is.character("a") # TRUE
is.logical(TRUE) # TRUE
# 转换
as.numeric("123") # 123
as.character(123) # "123"
as.integer(3.9) # 3(截断)
as.logical(1) # TRUE
as.logical(0) # FALSE
NA 与 NULL
# NA:缺失值
x <- c(1, 2, NA, 4)
is.na(x) # FALSE FALSE TRUE FALSE
sum(x, na.rm = TRUE) # 7 忽略缺失
# NULL:不存在
y <- NULL
is.null(y) # TRUE
因子(Factor)
# 分类变量
gender <- factor(c("男", "女", "男"))
levels(gender) # "男" "女"
table(gender) # 频数统计
# 有序因子
grade <- factor(c("低", "高", "中"),
levels = c("低", "中", "高"),
ordered = TRUE)
数据结构总览
向量 Vector 一维,同类型
矩阵 Matrix 二维,同类型
数组 Array 多维,同类型
列表 List 一维,可不同类型
数据框 Data Frame 二维,每列可不同类型(最常用)
因子 Factor 分类变量
R 判断语句
R 判断语句
R 使用 if、if-else、ifelse 与 switch 实现条件逻辑。
if 语句
score <- 85
if (score >= 60) {
print("及格")
}
if-else 语句
if (score >= 90) {
print("优秀")
} else if (score >= 60) {
print("及格")
} else {
print("不及格")
}
ifelse(向量化)
# 向量化的条件判断,返回向量
scores <- c(45, 78, 92, 55)
results <- ifelse(scores >= 60, "及格", "不及格")
print(results) # "不及格" "及格" "及格" "不及格"
# 嵌套 ifelse
grades <- ifelse(scores >= 90, "A",
ifelse(scores >= 80, "B",
ifelse(scores >= 70, "C", "D")))
switch 语句
# 根据索引或值选择
choice <- "b"
switch(choice,
a = print("选择了 A"),
b = print("选择了 B"),
c = print("选择了 C"),
print("默认选项")
)
逻辑条件组合
age <- 25
has_id <- TRUE
if (age >= 18 && has_id) {
print("允许进入")
}
if (age < 18 || !has_id) {
print("禁止进入")
}
缺失值判断
x <- NA
if (is.na(x)) {
print("x 是缺失值")
} else if (x > 0) {
print("x 是正数")
} else {
print("x 是负数或零")
}
R 循环
R 循环
R 提供 for、while、repeat 三种循环,但推荐优先使用向量化与 apply 家族。
for 循环
# 遍历向量
for (i in 1:5) {
print(i)
}
# 遍历值
fruits <- c("苹果", "香蕉", "橙子")
for (f in fruits) {
print(f)
}
# 带索引
for (i in seq_along(fruits)) {
print(paste(i, fruits[i]))
}
while 循环
count <- 0
while (count < 5) {
print(count)
count <- count + 1
}
repeat 循环
# repeat 至少执行一次,需手动 break
x <- 1
repeat {
print(x)
x <- x + 1
if (x > 3) break
}
break 与 next
# break:退出循环
for (i in 1:10) {
if (i == 5) break
print(i) # 1 2 3 4
}
# next:跳过本次(类似 continue)
for (i in 1:10) {
if (i %% 2 == 0) next
print(i) # 1 3 5 7 9
}
apply 家族(更 R 风格)
m <- matrix(1:12, nrow = 3)
apply(m, 1, sum) # 按行求和
apply(m, 2, mean) # 按列求均值
lapply(list(1:3, 4:6), sum) # 返回列表
sapply(list(1:3, 4:6), sum) # 返回向量
# 遍历数据框列
df <- data.frame(a = 1:3, b = 4:6)
sapply(df, mean) # a=2 b=5
向量化的优势
# 避免循环,直接向量运算(快很多)
x <- 1:100000
y <- x * 2 # 向量化,无循环
# for 循环写法(慢,不推荐)
y <- numeric(100000)
for (i in 1:100000) y[i] <- x[i] * 2
R 函数
R 函数
函数是 R 代码复用的核心,支持默认参数、匿名函数等特性。
定义函数
# 基本函数
add <- function(a, b) {
result <- a + b
return(result)
}
print(add(3, 5)) # 8
# 简写(最后一行自动返回)
multiply <- function(a, b) a * b
print(multiply(3, 4)) # 12
默认参数
greet <- function(name, prefix = "你好") {
paste(prefix, name)
}
greet("张三") # "你好 张三"
greet("李四", "早上好") # "早上好 李四"
可变参数(...)
sum_all <- function(...) {
args <- list(...)
sum(unlist(args))
}
sum_all(1, 2, 3) # 6
sum_all(1, 2, 3, 4, 5) # 15
命名参数与位置参数
f <- function(a, b, c) a + b + c
f(1, 2, 3) # 位置参数
f(c = 3, a = 1, b = 2) # 命名参数(顺序可乱)
匿名函数
# 一次性使用,不命名
result <- sapply(1:5, function(x) x^2)
print(result) # 1 4 9 16 25
# 配合 apply
m <- matrix(1:9, nrow = 3)
apply(m, 1, function(row) max(row))
作用域
global_var <- 10 # 全局
test <- function() {
local_var <- 20 # 局部
print(global_var) # 可读全局
# global_var <- 30 # 这样是新建局部变量
}
test()
# print(local_var) # 报错:找不到
函数作为参数
apply_twice <- function(f, x) {
f(f(x))
}
apply_twice(function(v) v * 2, 5) # 20
R 字符串
R 字符串
R 中字符串使用双引号或单引号,提供丰富的字符串处理函数。
创建字符串
s1 <- "Hello"
s2 <- 'World'
paste(s1, s2) # "Hello World"(默认空格连接)
paste(s1, s2, sep = "-") # "Hello-World"
paste0(s1, s2) # "HelloWorld"(无分隔)
字符串属性
s <- "Hello R"
nchar(s) # 7 字符数
toupper(s) # "HELLO R"
tolower(s) # "hello r"
substring(s, 1, 5) # "Hello" 截取
substr(s, 7, 7) # "R"
字符串拼接
# 向量拼接
str_c(c("a", "b"), c("1", "2")) # 需 stringr 包
# 基础方式
paste(c("a", "b"), collapse = "-") # "a-b"
# sprintf 格式化
sprintf("姓名: %s, 年龄: %d", "张三", 28)
# "姓名: 张三, 年龄: 28"
查找与替换
s <- "Hello World"
grepl("World", s) # TRUE 是否包含
regexpr("o", s) # 第一次出现位置
gregexpr("o", s) # 所有出现位置
gsub("World", "R", s) # "Hello R" 替换
sub("l", "L", s) # "HeLlo World" 只替换第一个
strsplit(s, " ") # 按空格分割 -> list
stringr 包(推荐)
library(stringr)
str_detect(s, "World") # TRUE
str_extract(s, "l+") # "ll"
str_replace(s, "World", "R")
str_split(s, " ")
str_trim(" 空格 ") # "空格" 去空白
str_length(s) # 11
编码处理
# 中文编码
s <- "中文测试"
Encoding(s) # "UTF-8"
enc2utf8(s) # 转 UTF-8
iconv(s, from = "UTF-8", to = "GBK") # 转 GBK
R 列表
R 列表(List)
列表是 R 中灵活的数据结构,可以容纳不同类型的元素,包括向量、矩阵、数据框甚至其他列表。
创建列表
my_list <- list(
name = "张三",
age = 28,
scores = c(85, 92, 78),
is_student = TRUE
)
print(my_list)
访问列表元素
# 用 $ 访问(最常用)
my_list$name # "张三"
my_list$scores # 85 92 78
# 用 [[]] 取元素本身
my_list[["age"]] # 28
my_list[[3]] # 85 92 78(按位置)
# 用 [] 返回子列表(仍是 list)
my_list["name"] # $name [1] "张三"(是 list)
修改与添加
my_list$age <- 29 # 修改
my_list$city <- "北京" # 添加
my_list$scores <- NULL # 删除
# 合并列表
l1 <- list(a = 1)
l2 <- list(b = 2)
combined <- c(l1, l2) # $a $b
列表的列表(嵌套)
users <- list(
user1 = list(name = "张三", age = 28),
user2 = list(name = "李四", age = 30)
)
users$user1$name # "张三"
users[[2]][["age"]] # 30
列表操作函数
length(my_list) # 元素个数
names(my_list) # 元素名
unlist(my_list) # 展平为向量(类型需一致)
# lapply:对每个元素应用函数
lapply(list(1:3, 4:6), sum) # 返回列表
# unlist 结果
unlist(lapply(list(1:3, 4:6), sum)) # 5 15
列表转数据框
# 等长列表转数据框
df <- as.data.frame(list(
name = c("张三", "李四"),
age = c(28, 30)
))
print(df)
R 矩阵
R 矩阵(Matrix)
矩阵是二维的同类元素集合,适合数值计算与线性代数操作。
创建矩阵
# matrix(数据, nrow, ncol, byrow)
m <- matrix(1:12, nrow = 3, ncol = 4)
print(m)
# [,1] [,2] [,3] [,4]
# [1,] 1 4 7 10
# [2,] 2 5 8 11
# [3,] 3 6 9 12
# 按行填充
m2 <- matrix(1:6, nrow = 2, byrow = TRUE)
# [,1] [,2] [,3]
# [1,] 1 2 3
# [2,] 4 5 6
访问元素
m <- matrix(1:12, nrow = 3)
m[1, 2] # 第 1 行第 2 列 -> 4
m[1, ] # 第 1 行全部
m[, 2] # 第 2 列全部
m[1:2, 3:4] # 子矩阵
m[3, 2, drop = FALSE] # 保持矩阵形状
行列名
m <- matrix(1:6, nrow = 2,
dimnames = list(c("行1", "行2"),
c("A", "B", "C")))
m["行1", "B"] # 2
rownames(m) # "行1" "行2"
colnames(m) # "A" "B" "C"
矩阵运算
a <- matrix(1:4, nrow = 2)
b <- matrix(5:8, nrow = 2)
a + b # 元素加法
a * b # 元素乘法
a %*% b # 矩阵乘法
t(a) # 转置
diag(a) # 对角线
solve(a) # 逆矩阵
det(a) # 行列式
rowSums(a) # 行和
colSums(a) # 列和
rowMeans(a) # 行均值
矩阵与向量
# 结合 rbind/cbind
r1 <- c(1, 2, 3)
r2 <- c(4, 5, 6)
rbind(r1, r2) # 按行合并
cbind(r1, r2) # 按列合并
# 矩阵转向量
as.vector(matrix(1:4, nrow = 2))
R 数组
R 数组(Array)
数组是多维数据结构(维度 ≥ 3),矩阵是数组的二维特例。
创建数组
# array(数据, dim = c(维度1, 维度2, 维度3...))
arr <- array(1:24, dim = c(2, 3, 4))
# 2 行 3 列 4 层
# 指定维度名称
arr2 <- array(1:8, dim = c(2, 2, 2),
dimnames = list(c("r1", "r2"),
c("c1", "c2"),
c("layer1", "layer2")))
访问数组元素
arr <- array(1:24, dim = c(2, 3, 4))
arr[1, 2, 3] # 第 1 行第 2 列第 3 层
arr[1, , ] # 第 1 行所有层
arr[, , 1] # 第 1 层(得到矩阵)
arr[1, 2, ] # 一个向量
数组运算
# 与向量/矩阵类似,支持元素级运算
arr + 1
arr * 2
# 维度操作
dim(arr) # 2 3 4
length(arr) # 24
apply(arr, 3, sum) # 每层求和
apply(arr, c(1, 2), sum) # 按行列聚合
# 转置(置换维度)
aperm(arr, c(3, 2, 1)) # 重排维度
创建规则的数组
# 重复填充
array(0, dim = c(3, 3, 3)) # 全 0
array(rep(1, 8), dim = c(2, 2, 2)) # 全 1
数组的应用场景
1. 多维观测数据(时间 × 变量 × 个体)
2. 图像数据(宽 × 高 × 通道)
3. 模型输出(批量 × 类别)
4. 模拟实验的多维结果
R 因子
R 因子(Factor)
因子用于表示分类变量,在统计建模中至关重要(回归、方差分析都依赖因子)。
创建因子
# 基本因子
gender <- factor(c("男", "女", "男", "女"))
print(gender)
# Levels: 男 女
# 指定水平(顺序)
grade <- factor(c("高", "低", "中"),
levels = c("低", "中", "高"))
print(grade)
# Levels: 低 中 高
因子属性
levels(gender) # 所有水平
nlevels(gender) # 水平数量
table(gender) # 频数表
# 男 女
# 2 2
有序因子
# 有序:水平有大小关系
temp <- factor(c("低", "高", "中"),
levels = c("低", "中", "高"),
ordered = TRUE)
temp[1] < temp[2] # TRUE(低 < 高)
因子转数值
# 先转字符再转数值,避免得到水平编号
scores <- factor(c("85", "90", "78"))
as.numeric(scores) # 1 2 3(水平编号,不是原值!)
as.numeric(as.character(scores)) # 85 90 78 ✓
# 或
as.numeric(levels(scores))[scores]
修改因子
# 添加水平
gender <- factor(c("男", "女"))
levels(gender) <- c(levels(gender), "未知")
gender <- c(gender, "未知") # 添加该水平的观察值
# 重命名水平
levels(gender) <- c("M", "F", "U")
# 删除未使用的水平
gender2 <- droplevels(gender)
因子在建模中的作用
# 回归中因子自动生成哑变量
df <- data.frame(
y = c(10, 12, 15, 18),
group = factor(c("A", "A", "B", "B"))
)
lm(y ~ group, data = df) # groupB 的系数体现差异
R 数据框
R 数据框(Data Frame)
数据框是 R 数据分析最常用的结构,类似 Excel 表格:行是观测,列是变量。
创建数据框
df <- data.frame(
name = c("张三", "李四", "王五"),
age = c(28, 30, 25),
score = c(85, 92, 78),
stringsAsFactors = FALSE # 字符串不转因子
)
print(df)
访问数据
# $ 访问列
df$name # "张三" "李四" "王五"
# 索引
df[1, 2] # 第 1 行第 2 列 -> 28
df[1, ] # 第 1 行
df[, "age"] # age 列
df["name"] # 返回数据框(单列)
# 常用函数
nrow(df) # 3 行数
ncol(df) # 3 列数
dim(df) # 3 3
names(df) # 列名
head(df, 2) # 前 2 行
summary(df) # 统计摘要
添加与修改列
# 添加列
df$grade <- c("B", "A", "C")
df$pass <- df$score >= 60
# 添加行
new_row <- data.frame(name = "赵六", age = 27,
score = 88, grade = "B", pass = TRUE)
df <- rbind(df, new_row)
筛选与排序
# 条件筛选
df[df$age > 26, ]
df[df$score >= 85 & df$age < 30, ]
# subset 函数
subset(df, age > 26, select = c(name, score))
# 排序
df[order(df$score, decreasing = TRUE), ] # 分数降序
df[order(df$age), ] # 年龄升序
dplyr 包(现代数据处理)
library(dplyr)
df %>%
filter(age > 26) %>%
select(name, score) %>%
arrange(desc(score)) %>%
mutate(level = ifelse(score >= 85, "优秀", "良好")) %>%
group_by(level) %>%
summarise(avg_age = mean(age))
R 数据重塑
R 数据重塑
数据分析常需在宽格式与长格式之间转换,以及行列转换。
宽格式 vs 长格式
# 宽格式(每个变量一列)
# id q1 q2 q3
# 1 1 85 90 88
# 2 2 78 82 80
# 长格式(每个观测一行,变量名成列)
# id question score
# 1 1 q1 85
# 2 1 q2 90
# 3 2 q1 78
reshape2 / tidyr 包
library(tidyr)
# 宽转长: pivot_longer
long <- df %>%
pivot_longer(cols = c(q1, q2, q3),
names_to = "question",
values_to = "score")
# 长转宽: pivot_wider
wide <- long %>%
pivot_wider(names_from = question,
values_from = score)
reshape() 基础函数
# 宽转长
long <- reshape(df,
direction = "long",
varying = c("q1", "q2", "q3"),
v.names = "score",
times = c("q1", "q2", "q3"))
行列转置
# t() 转置矩阵/数据框
t(data.frame(a = 1:3, b = 4:6))
# 列转行
library(tidyr)
pivot_longer(df, cols = everything(),
names_to = "variable", values_to = "value")
合并数据
# 按行合并(追加观测)
rbind(df1, df2)
# 按列合并(添加变量)
cbind(df1, df2)
# 按 key 合并(类似 SQL JOIN)
merge(df1, df2, by = "id")
merge(df1, df2, by = "id", all = TRUE) # 全外连接
merge(df1, df2, by.x = "id1", by.y = "id2")
聚合(aggregate)
# 分组统计
aggregate(score ~ group, data = df, FUN = mean)
aggregate(cbind(score, age) ~ group, data = df, FUN = sum)
R 包
R 包(Packages)
R 包是可复用的代码集合,CRAN 上有 2 万+ 包可供使用。
安装包
# 从 CRAN 安装
install.packages("ggplot2")
install.packages(c("dplyr", "tidyr", "stringr"))
# 从 GitHub 安装
# install.packages("devtools")
# devtools::install_github("hadley/ggplot2")
# 指定镜像(中国用户)
install.packages("ggplot2",
repos = "https://mirrors.tuna.tsinghua.edu.cn/CRAN/")
加载与使用
# 加载包
library(ggplot2) # 推荐
require(dplyr) # 也可,不强制
# 查看帮助
help(package = "dplyr")
?ggplot
# 已安装包列表
installed.packages()
常用包推荐
数据处理: dplyr, tidyr, data.table
可视化: ggplot2, plotly, echarts4r
统计建模: stats, lmtest, car
机器学习: caret, randomForest, xgboost
字符串: stringr
日期: lubridate
数据导入: readr, readxl, jsonlite, DBI
报告: rmarkdown, knitr
包版本管理
# 查看版本
packageVersion("ggplot2") # '3.4.4'
sessionInfo() # 完整环境信息
# 更新包
update.packages()
# 卸载
remove.packages("ggplot2")
编写自己的包(简单流程)
# 用 usethis 初始化
# install.packages("usethis")
usethis::create_package("mypackage")
usethis::use_r("hello")
# 目录结构
# mypackage/
# ├── DESCRIPTION 元数据
# ├── NAMESPACE 导出声明
# ├── R/ 源码
# └── man/ 文档
# 构建与安装
# R CMD build mypackage
# R CMD INSTALL mypackage_0.1.0.tar.gz
R CSV 文件
R CSV 文件读写
CSV 是最常用的数据交换格式,R 提供 read.csv 与 readr 包读取。
读取 CSV
# 基础读取
df <- read.csv("data.csv")
print(head(df))
# 常用参数
df <- read.csv("data.csv",
header = TRUE, # 首行是列名
sep = ",", # 分隔符
encoding = "UTF-8", # 编码
stringsAsFactors = FALSE, # 字符串不转因子
na.strings = c("", "NA") # 缺失值标记
)
# 指定列类型
df <- read.csv("data.csv", colClasses = c(
id = "integer",
name = "character",
price = "numeric"
))
readr 包(更快更友好)
library(readr)
df <- read_csv("data.csv")
# 自动识别类型,输出解析报告
# 编码问题用 locale
df <- read_csv("data.csv", locale = locale(encoding = "UTF-8"))
df <- read_csv("data.csv", locale = locale(encoding = "GBK"))
写入 CSV
# 基础写入
write.csv(df, "output.csv", row.names = FALSE)
# row.names = FALSE 不写行号
# readr 写入
library(readr)
write_csv(df, "output.csv")
# 追加
write.table(df, "log.csv", append = TRUE,
sep = ",", col.names = FALSE)
大文件处理
# data.table 高效读取
library(data.table)
dt <- fread("big_data.csv") # 极快
# 分块读取
con <- file("big.csv", "r")
chunk <- read.csv(con, nrows = 1000)
while (nrow(chunk) > 0) {
# 处理 chunk
chunk <- read.csv(con, nrows = 1000)
}
close(con)
常见问题
1. 中文乱码:设置 encoding = "UTF-8" 或 "GBK"
2. 列名带特殊字符:用 check.names = FALSE
3. 分隔符不是逗号:sep 参数(如 " " 制表符)
4. 数字变字符:检查是不是有逗号/特殊字符
R Excel 文件
R Excel 文件读写
R 通过 readxl、openxlsx、writexl 等包读写 Excel 文件。
读取 Excel
# readxl:只读,无需 Java
library(readxl)
df <- read_excel("data.xlsx")
df <- read_excel("data.xlsx", sheet = 2) # 按序号
df <- read_excel("data.xlsx", sheet = "数据表") # 按名称
df <- read_excel("data.xlsx", range = "A1:D10") # 指定范围
# 列出所有工作表
excel_sheets("data.xlsx")
读取多个工作表
library(readxl)
sheets <- excel_sheets("data.xlsx")
all_data <- lapply(sheets, function(s) {
read_excel("data.xlsx", sheet = s)
})
names(all_data) <- sheets
# all_data$Sheet1, all_data$Sheet2 ...
写入 Excel
# writexl:轻量,纯 R 实现
library(writexl)
write_xlsx(df, "output.xlsx")
# openxlsx:功能更全(样式、多表)
library(openxlsx)
# 多工作表
list_of_dfs <- list(销售 = df1, 库存 = df2)
write.xlsx(list_of_dfs, "report.xlsx")
# 自定义样式
wb <- createWorkbook()
addWorksheet(wb, "数据")
writeData(wb, "数据", df)
writeDataTable(wb, "数据", df, startCol = 5)
saveWorkbook(wb, "styled.xlsx", overwrite = TRUE)
xlconnect / xlsx 包(需 Java)
# 如需保留公式或复杂格式
# install.packages("xlsx") # 需要 Java 环境
# library(xlsx)
# df <- read.xlsx("data.xlsx", sheetIndex = 1)
# write.xlsx(df, "out.xlsx")
常见问题
1. 读取中文列名乱码:read_excel 默认处理较好
2. 数值精度:注意 Excel 浮点存储
3. 大文件:openxlsx 比 readxl 慢,选 readxl 读
4. 公式单元格:readxl 返回缓存值
R XML 文件
R XML 文件处理
R 通过 XML 包或 xml2 包读取和解析 XML 数据。
xml2 包(推荐)
# install.packages("xml2")
library(xml2)
# 读取 XML
doc <- read_xml("data.xml")
# 解析字符串
doc <- read_xml("<root><item>1</item></root>")
# 根元素
root <- xml_root(doc)
xml_name(root) # "root"
查询节点
library(xml2)
# 查找元素
items <- xml_find_all(doc, "//item")
first <- xml_find_first(doc, "//item")
# 取文本
xml_text(items)
# 取属性
xml_attr(items, "id")
# XPath 条件
xml_find_all(doc, "//book[@category='编程']")
xml_find_all(doc, "//book[price > 50]")
XML 包(经典)
library(XML)
# 解析
doc <- xmlParse("data.xml")
root <- xmlRoot(doc)
# 遍历
books <- xpathApply(doc, "//book", function(node) {
xmlValue(node[["title"]])
})
print(books)
# 转数据框
df <- xmlToDataFrame("data.xml")
创建 XML
library(xml2)
doc <- xml_new_root("bookstore")
book <- xml_add_child(doc, "book")
xml_set_attr(book, "id", "1001")
xml_add_child(book, "title", "R 语言教程")
xml_add_child(book, "price", "59")
# 输出
as.character(doc)
write_xml(doc, "output.xml")
解析网络 XML(RSS)
library(xml2)
# 获取 RSS
rss <- read_xml("https://example.com/feed.xml")
titles <- xml_find_all(rss, "//item/title")
xml_text(titles)
R JSON 文件
R JSON 文件处理
R 通过 jsonlite 包读取、解析和生成 JSON 数据,是 API 交互的标配。
解析 JSON
# install.packages("jsonlite")
library(jsonlite)
# 解析字符串
json <- '{"name": "张三", "age": 28}'
data <- fromJSON(json)
print(data$name) # "张三"
print(data$age) # 28
# 解析文件
data <- fromJSON("data.json")
# 解析 URL(API 接口)
api_data <- fromJSON("https://api.example.com/data")
生成 JSON
library(jsonlite)
# 列表转 JSON
toJSON(list(name = "张三", age = 28))
# 数据框转 JSON
df <- data.frame(name = c("张三", "李四"),
score = c(85, 92))
toJSON(df)
# [{"name":"张三","score":85},{"name":"李四","score":92}]
# 美化输出
toJSON(df, pretty = TRUE)
# 写入文件
write_json(df, "output.json")
write_json(df, "output.json", pretty = TRUE)
嵌套 JSON
# 复杂 JSON 用 simplifyVector = FALSE
json <- '{"user": {"name": "张三", "tags": ["A", "B"]}}'
data <- fromJSON(json, simplifyVector = FALSE)
data$user$name # "张三"
data$user$tags[[1]] # "A"
# 嵌套数据框
data <- fromJSON("complex.json")
data$results # 自动展开为数据框
JSON 与数据框互转
library(jsonlite)
# 数据框 → JSON → 数据框
json <- toJSON(df)
df2 <- fromJSON(json)
# 列表列(每行为嵌套对象)
df$detail <- lapply(1:nrow(df), function(i) {
list(level = "A", note = paste0("记录", i))
})
toJSON(df)
与 API 交互完整示例
library(jsonlite)
library(httr)
# GET 请求
resp <- GET("https://api.example.com/users",
query = list(page = 1))
data <- fromJSON(content(resp, "text"))
# POST 请求
resp <- POST("https://api.example.com/login",
body = list(user = "admin", pwd = "123"),
encode = "json")
result <- fromJSON(content(resp, "text"))
R MySQL 连接
R MySQL 数据库连接
R 通过 RMySQL、DBI 等包连接 MySQL 数据库进行数据读写。
1. 安装驱动
# Windows/Linux
install.packages("RMySQL")
install.packages("DBI")
# macOS 可能需要配置
# brew install mysql-connector-c
# install.packages("RMySQL", type = "source")
2. 建立连接
library(DBI)
library(RMySQL)
con <- dbConnect(
MySQL(),
host = "localhost", # 服务器地址
port = 3306, # 端口
dbname = "shop", # 数据库名
user = "root", # 用户名
password = "123456" # 密码
)
print(con)
3. 查询数据
# 直接查询(返回数据框)
df <- dbGetQuery(con, "SELECT id, name, price FROM products")
print(head(df))
# 参数化查询(防注入)
df <- dbGetQuery(con,
"SELECT * FROM products WHERE price > ?",
params = list(50))
4. 写入数据
# 执行非查询语句
dbExecute(con, "INSERT INTO products (name, price) VALUES ('测试', 9.9)")
# 数据框批量写入
new_data <- data.frame(
name = c("商品A", "商品B"),
price = c(19.9, 29.9)
)
dbWriteTable(con, "products", new_data, append = TRUE)
5. 事务处理
dbBegin(con)
tryCatch({
dbExecute(con, "UPDATE account SET balance = balance - 100 WHERE id = 1")
dbExecute(con, "UPDATE account SET balance = balance + 100 WHERE id = 2")
dbCommit(con) # 提交
}, error = function(e) {
dbRollback(con) # 回滚
print(e$message)
})
6. 关闭连接
# 用完必须关闭
dbDisconnect(con)
# 查看所有连接
dbListConnections(MySQL())
常见问题
1. 中文乱码:连接后执行 SET NAMES utf8mb4
dbExecute(con, "SET NAMES utf8mb4")
2. 时区问题: SET time_zone = '+08:00'
3. 连接超时:适当调大 timeout 参数
R 绘图 - 饼图
R 绘图 - 饼图(Pie Chart)
饼图用于展示各类别占比,R 的基础绘图与 ggplot2 均可实现。
基础饼图
# 基础 pie()
slices <- c(10, 20, 30, 40)
labels <- c("A", "B", "C", "D")
pie(slices, labels = labels,
main = "类别占比饼图",
col = c("red", "blue", "green", "yellow"))
带百分比的饼图
slices <- c(10, 20, 30, 40)
labels <- c("A", "B", "C", "D")
pct <- round(slices / sum(slices) * 100)
labels2 <- paste(labels, pct, "%", sep = " ")
pie(slices, labels = labels2,
col = rainbow(length(slices)),
main = "带百分比饼图")
3D 饼图(plotrix 包)
# install.packages("plotrix")
library(plotrix)
pie3D(slices,
labels = labels,
explode = 0.1, # 分离
main = "3D 饼图",
col = rainbow(length(slices)))
ggplot2 饼图
library(ggplot2)
df <- data.frame(
category = c("A", "B", "C", "D"),
value = c(10, 20, 30, 40)
)
ggplot(df, aes(x = "", y = value, fill = category)) +
geom_bar(stat = "identity", width = 1) +
coord_polar("y", start = 0) +
theme_void() +
labs(title = "ggplot2 饼图")
饼图注意事项
1. 类别过多(>5)时优先用条形图
2. 比例接近时不易比较,用条形图更直观
3. 3D 饼图有视觉误导,慎用
4. 加标签与颜色提高可读性
R 绘图 - 条形图
R 绘图 - 条形图(Bar Chart)
条形图是分类数据最常用的可视化方式。
基础条形图
# 简单向量
counts <- c(12, 25, 18, 30)
names(counts) <- c("A", "B", "C", "D")
barplot(counts,
main = "基础条形图",
xlab = "类别",
ylab = "数量",
col = "steelblue")
水平条形图
barplot(counts, horiz = TRUE,
main = "水平条形图",
xlab = "数量",
col = "tomato")
分组条形图
# 矩阵数据
data <- matrix(c(10, 15, 20, 12),
nrow = 2, byrow = TRUE)
colnames(data) <- c("A", "B")
rownames(data) <- c("2025", "2026")
barplot(data,
beside = TRUE, # 并排(TRUE)或堆叠(FALSE)
legend.text = rownames(data),
col = c("lightblue", "orange"),
main = "分组条形图",
ylab = "数值")
ggplot2 条形图
library(ggplot2)
df <- data.frame(
category = c("A", "B", "C", "D"),
value = c(12, 25, 18, 30)
)
# 单系列
ggplot(df, aes(x = category, y = value)) +
geom_bar(stat = "identity", fill = "steelblue") +
labs(title = "ggplot2 条形图", x = "类别", y = "数量")
# 分组
df2 <- data.frame(
year = rep(c("2025", "2026"), each = 4),
category = rep(c("A", "B", "C", "D"), 2),
value = c(10, 15, 20, 12, 14, 18, 22, 16)
)
ggplot(df2, aes(x = category, y = value, fill = year)) +
geom_bar(stat = "identity", position = "dodge") +
theme_minimal()
数值标签
# 基础绘图加标签
bp <- barplot(counts, col = "steelblue", ylim = c(0, 35))
text(bp, counts, labels = counts, pos = 3)
# ggplot2
ggplot(df, aes(x = category, y = value)) +
geom_bar(stat = "identity", fill = "steelblue") +
geom_text(aes(label = value), vjust = -0.5)
R 绘图 - 中文支持
R 绘图 - 中文支持
R 绘图默认字体不含中文字符,需要配置字体与编码解决乱码问题。
1. 绘图中文乱码问题
# 问题:plot 中中文显示为方块
plot(1:10, main = "中文标题") # 可能出现方块
# 解决:指定支持中文的字体
2. Windows 解决方案
# 指定宋体/微软雅黑
windowsFonts(yahei = windowsFont("Microsoft YaHei"))
plot(1:10, main = "中文标题",
family = "yahei")
# 全局设置
par(family = "yahei")
3. macOS 解决方案
# 用苹方或冬青黑体
par(family = "PingFang SC")
# 或
par(family = "Heiti SC")
4. Linux 解决方案
# 安装中文字体
# sudo apt install fonts-wqy-zenhei
par(family = "WenQuanYi Zen Hei")
# 或
par(family = "Noto Sans CJK SC")
5. showtext 包(通用方案)
# install.packages("showtext")
library(showtext)
# 加载系统字体
font_add("chinese", "C:/Windows/Fonts/msyh.ttc") # 路径示例
showtext_auto()
# 之后绘图自动支持中文
plot(1:10, main = "中文标题", xlab = "横轴", ylab = "纵轴")
# 从 Google Fonts 加载
# font_add_google("Noto Sans SC")
6. ggplot2 中文
library(ggplot2)
library(showtext)
showtext_auto()
ggplot(data.frame(x = 1:5, y = 1:5), aes(x, y)) +
geom_point() +
labs(title = "中文标题", x = "横轴", y = "纵轴") +
theme(text = element_text(family = "chinese"))
7. 保存图片
# PNG 保存时指定字体
png("plot.png", width = 800, height = 600, res = 96)
par(family = "yahei") # 或 showtext
plot(1:10, main = "中文标题")
dev.off()
R 绘图 - 函数曲线图
R 绘图 - 函数曲线图
R 的 curve() 函数可以绘制数学函数的图像,是教学与分析的常用工具。
基础函数曲线
# y = x^2
curve(x^2, from = -5, to = 5,
main = "y = x²", xlab = "x", ylab = "y")
# 指定函数
curve(sin(x), from = 0, to = 2*pi,
main = "正弦函数", col = "blue")
多条曲线叠加
# 先画第一条
curve(x^2, from = -3, to = 3, col = "red",
main = "多项式函数", ylim = c(0, 10))
# 叠加更多
curve(x^3, from = -3, to = 3, col = "blue", add = TRUE)
curve(2*x, from = -3, to = 3, col = "green", add = TRUE)
# 图例
legend("top", legend = c("x²", "x³", "2x"),
col = c("red", "blue", "green"), lty = 1)
正态分布曲线
# 标准正态
curve(dnorm(x), from = -4, to = 4,
main = "正态分布", ylab = "密度")
# 不同参数
curve(dnorm(x, mean = 0, sd = 1), from = -5, to = 5,
col = "red", lwd = 2)
curve(dnorm(x, mean = 0, sd = 2), add = TRUE, col = "blue")
curve(dnorm(x, mean = 2, sd = 1), add = TRUE, col = "green")
legend("topright", legend = c("N(0,1)", "N(0,2)", "N(2,1)"),
col = c("red", "blue", "green"), lty = 1)
分段函数
f <- function(x) {
ifelse(x < 0, -x, x^2)
}
curve(f(x), from = -3, to = 3, main = "分段函数")
ggplot2 绘制函数
library(ggplot2)
# 生成点
x <- seq(-5, 5, length.out = 200)
df <- data.frame(x = x, y = x^2)
ggplot(df, aes(x, y)) +
geom_line(color = "red") +
labs(title = "y = x²", x = "x", y = "y") +
theme_minimal()
填充区域
curve(x^2, from = -3, to = 3, main = "填充区域")
polygon(c(-3, seq(-3, 3, 0.1), 3),
c(0, seq(-3, 3, 0.1)^2, 0),
col = rgb(0, 0, 1, 0.3), border = NA)
R 绘图 - 散点图
R 绘图 - 散点图(Scatter Plot)
散点图用于展示两个连续变量之间的关系,是探索性分析的基础图表。
基础散点图
# 模拟数据
x <- rnorm(100, mean = 50, sd = 10)
y <- 2 * x + rnorm(100, 0, 20)
plot(x, y,
main = "基础散点图",
xlab = "X 变量", ylab = "Y 变量",
col = "steelblue", pch = 16)
绘制回归线
plot(x, y, col = "steelblue", pch = 16,
main = "带回归线散点图")
# 线性回归线
abline(lm(y ~ x), col = "red", lwd = 2)
# 平滑曲线
lines(lowess(x, y), col = "green", lwd = 2)
按分组着色
group <- factor(rep(c("A", "B"), each = 50))
plot(x, y, col = c("red", "blue")[group], pch = 16,
main = "分组散点图")
legend("topleft",
legend = c("组 A", "组 B"),
col = c("red", "blue"), pch = 16)
气泡图(点大小表示第三维)
size <- runif(100, 1, 10)
plot(x, y, cex = size, # 点大小按 size
col = rgb(0, 0.5, 1, 0.5), pch = 16,
main = "气泡图")
ggplot2 散点图
library(ggplot2)
df <- data.frame(x, y, group)
ggplot(df, aes(x, y)) +
geom_point(color = "steelblue", alpha = 0.6) +
geom_smooth(method = "lm", se = TRUE, color = "red") +
labs(title = "ggplot2 散点图", x = "X", y = "Y") +
theme_minimal()
# 分组 + 颜色
ggplot(df, aes(x, y, color = group)) +
geom_point(size = 3, alpha = 0.7) +
scale_color_manual(values = c("red", "blue")) +
theme_minimal()
散点图矩阵
# 多变量关系
data(mtcars)
pairs(mtcars[, c("mpg", "hp", "wt", "cyl")],
main = "散点图矩阵",
pch = 20, col = "steelblue")
Java 中操作 R
Java 中操作 R
通过 Rserve 或 JRI,Java 程序可以调用 R 的统计计算能力。
方案对比
JRI: 进程内嵌 R(需本地 R,启动快但脆弱)
Rserve: 独立 R 服务(稳定,适合生产,推荐)
1. 启动 Rserve
# 在 R 中安装并启动
install.packages("Rserve")
library(Rserve)
Rserve(args = "--no-save") # 默认端口 6311
# 或带认证
Rserve(args = "--no-save --RS-auth")
# 配置文件 /etc/Rserv.conf:
# auth required
# plaintext enable
2. Maven 依赖
<dependency>
<groupId>org.rosuda.REngine</groupId>
<artifactId>Rserve</artifactId>
<version>1.8.1</version>
</dependency>
3. Java 连接并执行
import org.rosuda.REngine.Rserve.*;
public class RCallExample {
public static void main(String[] args) throws Exception {
// 连接 Rserve
RConnection c = new RConnection("localhost", 6311);
// 执行 R 代码
c.eval("x <- c(1,2,3,4,5)");
c.eval("y <- mean(x)");
// 获取结果
double mean = c.eval("y").asDouble();
System.out.println("平均值: " + mean);
// 传递数据给 R
c.assign("values", new double[]{1.5, 2.5, 3.5});
double result = c.eval("sum(values)").asDouble();
System.out.println("和: " + result);
c.close();
}
}
4. 返回数据框
// R 返回数据框
REXP result = c.eval("data.frame(name=c('A','B'), score=c(90,80))");
// 按列读取
String[] names = result.asList().at(0).asStrings();
double[] scores = result.asList().at(1).asDoubles();
5. 调用 R 绘图
// 在 R 中生成图片保存到文件
c.eval("png('/tmp/plot.png')");
c.eval("plot(1:10, main='Java 调用的 R 图')");
c.eval("dev.off()");
6. 异常处理与关闭
try (RConnection c = new RConnection()) {
// 使用连接
} catch (RserveException | REXPMismatchException e) {
e.printStackTrace();
}
// try-with-resources 自动关闭
7. 常见问题
1. 连接失败:确认 Rserve 已启动、端口开放
2. 认证失败:配置 Rserv.conf 或关闭认证
3. 中文乱码:设置 UTF-8 编码
4. 并发:为每个请求建连接或用连接池
R 语言实例
R 语言综合实例
通过一个"学生成绩分析"实例,串联 R 的读写、统计、可视化全流程。
1. 生成数据
set.seed(42) # 固定随机种子
students <- data.frame(
name = paste0("学生", 1:50),
class = rep(c("一班", "二班"), each = 25),
math = round(rnorm(50, 75, 10)),
english = round(rnorm(50, 70, 12)),
stringsAsFactors = FALSE
)
# 保证分数在 0-100
students$math <- pmax(0, pmin(100, students$math))
students$english <- pmax(0, pmin(100, students$english))
2. 数据概览
head(students)
summary(students)
# 各班人数
table(students$class)
# 成绩分布
hist(students$math, main = "数学成绩分布", col = "skyblue")
3. 统计分析
# 各班平均分
aggregate(cbind(math, english) ~ class,
data = students, FUN = mean)
# 相关性
cor(students$math, students$english)
# 总体均分
students$total <- students$math + students$english
mean(students$total)
# 最高分
students[which.max(students$total), ]
4. 可视化
library(ggplot2)
# 箱线图对比各班
ggplot(students, aes(x = class, y = math, fill = class)) +
geom_boxplot() +
labs(title = "两班数学成绩对比") +
theme_minimal()
# 散点图看相关
ggplot(students, aes(x = math, y = english, color = class)) +
geom_point(size = 3) +
geom_smooth(method = "lm") +
labs(title = "数学与英语成绩关系") +
theme_minimal()
5. 导出结果
# 保存清洗后数据
write.csv(students, "students_analysis.csv", row.names = FALSE)
# 保存图表
ggsave("score_boxplot.png", width = 8, height = 6)
6. 完整流程总结
数据生成/读取 → 概览清洗 → 分组统计
→ 相关性分析 → 可视化 → 导出报告
R 语言学习资源
R 语言学习资源与进阶方向
本教程之外,官方文档与社区提供了丰富的 R 学习资源。
官方资源
官网: r-project.org
文档: cran.r-project.org/manuals.html
包仓库: cran.r-project.org
RStudio: posit.co
R 帮助: help() / ?函数名 内置文档
经典书籍
入门:
《R 语言实战》(R in Action)
《R for Data Science》(R4DS, 免费在线)
进阶:
《Advanced R》
《ggplot2: Elegant Graphics for Data Analysis》
《The Elements of Statistical Learning》
常用扩展方向
数据科学: dplyr + tidyr + ggplot2 全家桶
机器学习: caret, tidymodels, xgboost
报告生成: R Markdown / Quarto
Shiny 应用: 交互式 Web 仪表盘
可视化: plotly, highcharter, leaflet(地图)
金融分析: quantmod, PerformanceAnalytics
生物信息: Bioconductor 生态
学习路径建议
1. 掌握基础语法与数据结构(向量/数据框)
2. 学会 dplyr 数据处理流程
3. 熟练 ggplot2 数据可视化
4. 掌握 R Markdown 报告输出
5. 按需学习建模/机器学习/Shiny
6. 多动手:Kaggle、TidyTuesday 实战
社区与问答
Stack Overflow: #r 标签
R-bloggers: 全球 R 博客聚合
R Weekly: 每周精选
知乎/公众号: 中文社区(数据分析、统计方向)
实践建议
1. 用真实数据分析练习
2. 参与 TidyTuesday 每周数据可视化
3. 尝试用 Shiny 部署一个仪表盘
4. 阅读高质量包源码(ggplot2 等)
5. 写自己的函数与包,提升工程化能力