数据分析的第一步永远是读取数据。真实数据通常存储在 CSV、TXT 等文件中,本章将学习如何用 R 读取外部数据文件,以及如何把分析结果导出保存。
一、数据文件常见格式
| 格式 | 扩展名 | 特点 |
|---|---|---|
| CSV | .csv |
逗号分隔,最通用的表格格式 |
| TXT | .txt |
制表符或自定义分隔符 |
| Excel | .xlsx |
需要额外包(如 readxl) |
本章重点:CSV 和 TXT,因为 R 内置函数就能处理,无需安装任何包。
二、准备工作:设置工作目录
R 需要知道去哪个文件夹找文件。
1. 查看当前工作目录
r
getwd()
运行结果:
txt
[1] "d:/develop/code/R"
2. 设置工作目录
setwd适合小型数据分析项目。大型项目(推荐用 here 包)
r
# ❌ 坏写法(换电脑就找不到)
setwd("d:/develop/code/R/data")
# ✅ 好写法(项目相对路径)
setwd("data")
建议:把数据文件放在工作目录下,读取时直接写文件名即可,不用写完整路径。
三、读取 CSV 文件
1. 先创建一个示例 CSV 文件
运行以下代码,自动生成一个练习用的 CSV 文件:
r
# 设置到你放数据文件的目录
setwd("data")
# 创建示例数据并保存为 CSV
students <- data.frame(
name = c("张三", "李四", "王五", "赵六", "孙七"),
gender = c("男", "女", "男", "男", "女"),
math = c(92, 88, 76, 65, 95),
chinese = c(85, 72, 95, 58, 88),
english = c(78, 90, 82, 70, 92),
stringsAsFactors = FALSE
)
write.csv(students, "students.csv", row.names = FALSE)
print("已生成 students.csv")
2. 用 read.csv() 读取
r
# 设置到你放数据文件的目录
setwd("data")
# 读取 CSV 文件
df <- read.csv("students.csv", stringsAsFactors = FALSE)
print(df)
运行结果:
txt
name gender math chinese english
1 张三 男 92 85 78
2 李四 女 88 72 90
3 王五 男 76 95 82
4 赵六 男 65 58 70
5 孙七 女 95 88 92
3. read.csv() 常用参数
r
# 设置到你放数据文件的目录
setwd("data")
df <- read.csv(
"students.csv",
header = TRUE, # 第一行是否为列名(默认 TRUE)
stringsAsFactors = FALSE, # 不自动将字符串转为因子
encoding = "UTF-8", # 编码(中文文件常用)
sep = "," # 分隔符(CSV 默认逗号)
)
4. 读取中文 CSV 的常见问题
如果读出来是乱码,尝试指定编码:
r
# 方法1:指定 UTF-8 编码
df <- read.csv("students.csv", fileEncoding = "UTF-8", stringsAsFactors = FALSE)
# 方法2:如果是 Windows 下 GBK 编码
df <- read.csv("students.csv", fileEncoding = "GBK", stringsAsFactors = FALSE)
四、读取 TXT 文件
1. 创建示例 TXT 文件
r
# 创建制表符分隔的 TXT 文件
students <- data.frame(
name = c("张三", "李四", "王五"),
math = c(92, 88, 76),
chinese = c(85, 72, 95),
stringsAsFactors = FALSE
)
write.table(students, "students.txt", sep = "\t", row.names = FALSE, quote = FALSE)
print("已生成 students.txt")
2. 用 read.table() 读取
r
# 读取制表符分隔的 TXT
df <- read.table("students.txt", header = TRUE, sep = "\t", stringsAsFactors = FALSE)
print(df)
运行结果:
txt
name math chinese
1 张三 92 85
2 李四 88 72
3 王五 76 95
3. read.csv vs read.table
| 函数 | 默认分隔符 | 适用场景 |
|---|---|---|
read.csv() |
逗号 , |
CSV 文件 |
read.table() |
空格/制表符 | TXT 文件,灵活指定分隔符 |
实际上 read.csv() 是 read.table() 的简化版:
r
# 这两行等价
read.csv("data.csv")
read.table("data.csv", header = TRUE, sep = ",")
4. 读取其他分隔符的文件
r
# 分号分隔
df <- read.table("data.csv", header = TRUE, sep = ";", stringsAsFactors = FALSE)
# 空格分隔
df <- read.table("data.txt", header = TRUE, sep = " ", stringsAsFactors = FALSE)
# 竖线分隔
df <- read.table("data.txt", header = TRUE, sep = "|", stringsAsFactors = FALSE)
五、读取后检查数据
养成读取后立即检查的好习惯:
r
df <- read.csv("students.csv", stringsAsFactors = FALSE)
# 第一步:看前几行
head(df)
# 第二步:看结构
str(df)
# 第三步:看维度
dim(df)
nrow(df)
ncol(df)
# 第四步:看列名
names(df)
# 第五步:快速统计
summary(df)
六、导出数据
1. 导出为 CSV
r
df <- data.frame(
name = c("张三", "李四", "王五"),
math = c(92, 88, 76),
stringsAsFactors = FALSE
)
# 导出 CSV(不保存行号)
write.csv(df, "output.csv", row.names = FALSE)
2. 导出为 TXT
r
# 导出制表符分隔的 TXT
write.table(df, "output.txt", sep = "\t", row.names = FALSE, quote = FALSE)
3. 导出参数说明
r
write.csv(
df,
"output.csv",
row.names = FALSE, # 不保存行号(通常不需要)
quote = FALSE, # 不给字符串加引号
fileEncoding = "UTF-8" # 指定编码
)
七、读写完整流程示例
r
# ==============================
# 完整流程:读取 → 处理 → 导出
# ==============================
# 1. 创建原始数据并保存
raw <- data.frame(
name = c("张三", "李四", "王五", "赵六", "孙七"),
gender = c("男", "女", "男", "男", "女"),
math = c(92, 88, 76, 65, 95),
chinese = c(85, 72, 95, 58, 88),
english = c(78, 90, 82, 70, 92),
stringsAsFactors = FALSE
)
write.csv(raw, "scores_raw.csv", row.names = FALSE)
# 2. 读取数据
df <- read.csv("scores_raw.csv", stringsAsFactors = FALSE)
# 3. 数据处理:计算总分、平均分、等级
df$total <- df$math + df$chinese + df$english
df$average <- round(df$total / 3, 1)
df$grade <- ifelse(df$average >= 90, "优秀",
ifelse(df$average >= 80, "良好",
ifelse(df$average >= 60, "及格", "不及格")))
# 4. 导出处理后的数据
write.csv(df, "scores_result.csv", row.names = FALSE)
print("处理完成,已导出 scores_result.csv")
八、综合实战练习(可直接复制运行)
r
# ==============================
# R 综合练习:文件读写实战
# 场景:从原始数据到分析报告
# ==============================
# 1. 创建模拟数据(模拟从外部获取的原始数据)
set.seed(42)
n <- 15
raw_data <- data.frame(
id = 1:n,
name = paste0("学生", sprintf("%02d", 1:n)),
gender = sample(c("男", "女"), n, replace = TRUE),
class = sample(c("A班", "B班"), n, replace = TRUE),
math = round(runif(n, 40, 100)),
chinese = round(runif(n, 40, 100)),
english = round(runif(n, 40, 100)),
stringsAsFactors = FALSE
)
# 故意加入几个缺失值
raw_data$math[3] <- NA
raw_data$english[7] <- NA
# 2. 保存原始数据
write.csv(raw_data, "exam_raw.csv", row.names = FALSE)
print("原始数据已保存到 exam_raw.csv")
# 3. 重新读取(模拟从文件开始工作流)
df <- read.csv("exam_raw.csv", stringsAsFactors = FALSE)
print("=== 读取成功,前5行预览 ===")
print(head(df))
print(paste("共", nrow(df), "行", ncol(df), "列"))
# 4. 数据检查
print("=== 数据结构 ===")
str(df)
print("=== 缺失值检查 ===")
for (col in names(df)) {
na_count <- sum(is.na(df[[col]]))
if (na_count > 0) {
print(paste(col, "列有", na_count, "个缺失值"))
}
}
# 5. 处理缺失值(用该科平均分填充)
df$math[is.na(df$math)] <- round(mean(df$math, na.rm = TRUE))
df$english[is.na(df$english)] <- round(mean(df$english, na.rm = TRUE))
# 6. 计算分析指标
df$total <- df$math + df$chinese + df$english
df$average <- round(df$total / 3, 1)
df$grade <- ifelse(df$average >= 90, "优秀",
ifelse(df$average >= 80, "良好",
ifelse(df$average >= 60, "及格", "不及格")))
# 7. 排序
df <- df[order(df$total, decreasing = TRUE), ]
df$rank <- 1:nrow(df)
# 8. 导出最终结果
write.csv(df, "exam_result.csv", row.names = FALSE)
print("分析结果已导出到 exam_result.csv")
# 9. 输出摘要
print("=== 最终结果 ===")
print(df[, c("rank", "name", "class", "math", "chinese", "english", "total", "average", "grade")])
# 10. 按班级汇总导出
class_summary <- aggregate(
cbind(math, chinese, english, total) ~ class,
data = df,
FUN = mean
)
class_summary$math <- round(class_summary$math, 1)
class_summary$chinese <- round(class_summary$chinese, 1)
class_summary$english <- round(class_summary$english, 1)
class_summary$total <- round(class_summary$total, 1)
write.csv(class_summary, "exam_class_summary.csv", row.names = FALSE)
print("=== 班级汇总 ===")
print(class_summary)
运行结果:
txt
[1] "原始数据已保存到 exam_raw.csv"
[1] "=== 读取成功,前5行预览 ==="
id name gender class math chinese english
1 1 学生01 男 A班 84 97 81
2 2 学生02 男 B班 89 93 99
3 3 学生03 男 B班 NA 78 86
4 4 学生04 男 B班 81 98 74
5 5 学生05 女 B班 40 77 91
6 6 学生06 女 A班 90 60 51
[1] "共 15 行 7 列"
[1] "=== 数据结构 ==="
'data.frame': 15 obs. of 7 variables:
$ id : int 1 2 3 4 5 6 7 8 9 10 ...
$ name : chr "学生01" "学生02" "学生03" "学生04" ...
$ gender : chr "男" "男" "男" "男" ...
$ class : chr "A班" "B班" "B班" "B班" ...
$ math : int 84 89 NA 81 40 90 40 52 94 77 ...
$ chinese: int 97 93 78 98 77 60 61 64 87 42 ...
$ english: int 81 99 86 74 91 51 NA 90 82 54 ...
[1] "=== 缺失值检查 ==="
[1] "math 列有 1 个缺失值"
[1] "english 列有 1 个缺失值"
[1] "分析结果已导出到 exam_result.csv"
[1] "=== 最终结果 ==="
rank name class math chinese english total average grade
2 1 学生02 B班 89 93 99 281 93.7 优秀
9 2 学生09 A班 94 87 82 263 87.7 良好
1 3 学生01 A班 84 97 81 262 87.3 良好
4 4 学生04 B班 81 98 74 253 84.3 良好
3 5 学生03 B班 70 78 86 234 78.0 及格
14 6 学生14 A班 98 56 69 223 74.3 及格
5 7 学生05 B班 40 77 91 208 69.3 及格
8 8 学生08 A班 52 64 90 206 68.7 及格
6 9 学生06 A班 90 60 51 201 67.0 及格
12 10 学生12 A班 66 81 48 195 65.0 及格
11 11 学生11 B班 63 85 43 191 63.7 及格
15 12 学生15 A班 66 71 52 189 63.0 及格
10 13 学生10 A班 77 42 54 173 57.7 不及格
7 14 学生07 A班 40 61 70 171 57.0 不及格
13 15 学生13 A班 42 50 53 145 48.3 不及格
[1] "=== 班级汇总 ==="
class math chinese english total
1 A班 70.9 66.9 65.0 202.8
2 B班 68.6 86.2 78.6 233.4