R语言基础 (三):数据集,维度逻辑,和导入

大一/大二 R语言入门课程

尹俊贺

第二部分:数据集的定义与维度逻辑

数据集的定义:从对象到属性

在 R 语言中,数据集(Dataset)是 对象(Object) 的集合,其本质是存储在内存中的 递归或原子结构

  • 核心要素
    • 观测 (Observations):通常位于行,代表样本单元。
    • 变量 (Variables):通常位于列,代表特征量。
  • 存储准则
    • Homogeneous (同质):容器内所有元素必须具有相同的基本类型(如全为 numeric)。
    • Heterogeneous (异质):允许在同一个容器内嵌套不同的对象类型。

第三部分:五大结构深度解析与应用

结构分类:多维空间中的数据载体

我们可以根据 维度 (Dimension)内容性质 将 R 的数据集划分为以下层级:

维度 同质 (Homogeneous) 异质 (Heterogeneous)
1D 向量 (Vector): R 的原子单位 列表 (List): 万能容器
2D 矩阵 (Matrix): 线性代数核心 数据框 (Data Frame): 统计分析标准
nD 数组 (Array): 矩阵的泛化 (通常由嵌套列表实现)

核心应用场景与作用:

  1. 数据框 (Data Frame):社会科学研究的“黄金标准”。它是列表的一种特例,每列长度必须相等,允许不同类型的变量并存。
  2. 因子 (Factor):处理 分类变量(Nominal/Ordinal)的特殊向量,在回归分析中会自动转换为虚拟变量(Dummy Variables)。
  3. 列表 (List):当你运行一个线性回归 lm() 时,返回的结果就是一个复杂的列表,它能同时装下残差、系数和显著性水平。

第四部分:向量与矩阵的基础代码

向量与矩阵:从创建到索引

1. 向量的创建与类型检查

# 创建一个数值型向量
weights <- c(60, 72, 58, 90)
names(weights) <- c("UserA", "UserB", "UserC", "UserD")

# 检查属性
class(weights)  # 返回 "numeric"
length(weights) # 返回 4

2. 矩阵的切片 (Slicing)

# 创建一个 3x3 的矩阵
mat <- matrix(1:9, nrow = 3, byrow = TRUE)

# 索引练习
mat[2, ]    # 提取第 2 行所有元素
mat[, 3]    # 提取第 3 列所有元素
mat[1, 2]   # 提取第 1 行第 2 列的具体数值

矩阵 (Matrices):严格的同质容器

矩阵是二维数组,核心特征是 Homogeneous(同质性):所有元素必须是相同类型(如全是数字)。

1. 核心语法

# 语法结构
# matrix(data, nrow, ncol, byrow)
  • data: 数据源 (如 1:6)
  • nrow/ncol: 行数/列数
  • byrow: 填充方向

2. 维度守恒定律

如果数据源有 6 个数,你不能创建一个 的矩阵,因为那需要 9 个坑位!

实战演示:按行 vs 按列填充

这是一个经典的考点,请观察 byrow 参数如何改变数字的排列顺序。

# 场景 A:默认情况 (byrow = FALSE) -> "竖着填"
# 先填满第1列(1,2,3),再去填第2列
mat_col <- matrix(1:6, nrow = 3, ncol = 2, byrow = FALSE)

# 场景 B:开启按行 (byrow = TRUE) -> "横着填"
# 先填满第1行(1,2),再换行填第2行
mat_row <- matrix(1:6, nrow = 3, ncol = 2, byrow = TRUE)

# --- 打印结果对比 ---
list("按列填充(默认)" = mat_col, "按行填充(byrow=TRUE)" = mat_row)
$`按列填充(默认)`
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6

$`按行填充(byrow=TRUE)`
     [,1] [,2]
[1,]    1    2
[2,]    3    4
[3,]    5    6

第五部分:数据的智能化生成与检索

1. 向量的“批量生产”:

在 R 中,我们很少一个个手动输入数字,而是使用函数批量生成。

A. 重复 (Replicate)

使用 rep() 函数将现有元素进行复制。

# 1. 整体重复 times
rep(1:3, times = 2) 
# 输出: 1 2 3 1 2 3

# 2. 逐个重复 each
rep(c("A", "B"), each = 2) 
# 输出: "A" "A" "B" "B"

B. 序列 (Sequence)

使用 seq() 生成等差数列。

  • length.out (关键参数): 告诉 R 你一共想要多少个数,让 R 自动计算步长。这在合成矩阵时非常有用!
# 生成 5 个数,从 2013 开始
#
years <- seq(from = 2013, length.out = 5)
# 输出: 2013 2014 2015 2016 2017

2. 矩阵构建实战:从向量到表格

如何利用 length.out 生成的向量来动态构建矩阵?

# 1. 准备数据:假设有 5 个岛屿的数据
islands_data <- c(11506, 5500, 16988, 2968, 16)
n_islands <- length(islands_data)  # 自动获取长度 (5)

# 2. 智能生成年份:确保年份数量与岛屿数量一致!
#
years <- seq(from = 2013, length.out = n_islands)

# 3. 组装矩阵:将两组向量拼接
# 注意:matrix() 接收的是一个长向量,我们用 c() 把它们连起来
isl_mat <- matrix(c(years, islands_data), ncol = 2, byrow = FALSE)
colnames(isl_mat) <- c("Year", "Area") # 加个列名方便看

# 4. 头部预览:使用 head() 只看前几行
head(isl_mat, n = 3)
     Year  Area
[1,] 2013 11506
[2,] 2014  5500
[3,] 2015 16988

head() 是检查大数据集的第一步,避免一次性打印几万行数据卡死 RStudio。

3. 下标查询 (Subscripting):数据的精准定位

利用方括号 [] 和坐标来提取数据。逻辑是:对象[行坐标, 列坐标]

核心语法图解

  • x[i] : 向量第 i 个
  • x[i, ]: 矩阵第 i
  • x[, j]: 矩阵第 j
  • x[i, j]: 第 i 行 第 j 列

代码演示

# 引用上面的 isl_mat 矩阵

# 1. 提取第 2 行的所有信息
row_2 <- isl_mat[2, ] 

# 2. 提取第 2 列 (Area)
col_2 <- isl_mat[, 2]

# 3. 提取具体的值 (第1行,第2列)
val <- isl_mat[1, 2]

# 展示结果
list(行提取=row_2, 列提取=col_2[1:3], 具体值=val)
$行提取
Year Area 
2014 5500 

$列提取
[1] 11506  5500 16988

$具体值
 Area 
11506 

第四部分:数据分析的核心——数据框

1. 什么是数据框 (Data Frame)?

在 R 语言的所有数据结构中,数据框 (Data Frame) 是你处理日常数据(Excel, CSV)时最常打交道的格式。

核心定义

数据框是一个二维的表格,它结合了矩阵的结构和列表的灵活性。

  • 列 (Columns):代表变量 (Variables)。每一列必须包含相同类型的数据(如全是数字,或全是字符)。
  • 行 (Rows):代表观测 (Observations)。每一行代表一个样本(如一个病人、一个国家)。
  • 异质性 (Heterogeneous):这是它最强大的地方——不同的列可以是不同的数据类型

代码演示:创建你的第一个数据框

我们使用 data.frame() 函数来从头构建。

# 构建一个简单的病人数据表
#
patient_data <- data.frame(
  ID = c(1, 2, 3),                  # 数值型列
  Age = c(25, 34, 28),              # 数值型列
  Type = c("Type1", "Type2", "Type1"), # 字符型列
  Status = c("Poor", "Improved", "Excellent") # 字符型列
)

# 查看结构
print(patient_data)
  ID Age  Type    Status
1  1  25 Type1      Poor
2  2  34 Type2  Improved
3  3  28 Type1 Excellent

2. 核心对比:矩阵 (Matrix) vs 数据框

这是初学者最容易混淆的两个概念。虽然它们长得都很像“表格”,但底层逻辑完全不同。

矩阵 (Matrix)

  • 核心特征同质 (Homogeneous)
  • 规则:所有元素必须是同一种类型
  • 后果:如果你试图把字符和数字混在一起,数字会被强制变成字符。
  • 用途:数学计算、线性代数运算。

数据框 (Data Frame)

  • 核心特征异质 (Heterogeneous)
  • 规则每一列可以是不同的类型,但同一列内必须相同。
  • 后果:完美适配现实世界的数据(有姓名也有年龄)。
  • 用途:统计分析、绘图 (ggplot2)。

一句话总结:矩阵是数学工具,数据框是数据容器。

3. 数据框的操作:精准检索 (Indexing)

如何从数据框中提取我们需要的数据?我们有两种主要流派。

方式 A:矩阵式 (坐标法 [,])

将数据框视为矩阵,使用 [行, 列] 的坐标提取。

# 提取第 1 行,第 2 列的具体数值
#
val <- patient_data[1, 2]

# 提取整个第 2 列 (返回向量)
col_vec <- patient_data[, 2]

方式 B:列表式 (美元符号 $)

这是 R 语言特有的快捷方式,直接通过列名提取,代码可读性极高。

# 提取 'Age' 这一列
#
ages <- patient_data$Age

# 提取 'Status' 这一列
statuses <- patient_data$Status

在实际写代码时,90% 的情况我们会用 $ 符号,因为它支持代码自动补全!

第五部分:进阶多维结构 (Arrays)

4. 数组 (Arrays):突破二维的限制

如果矩阵是 2D 的,那么数组 (Array) 就是 N-Dimension (多维) 的推广。

  • 定义:具有 N 个维度的同质数据集合。
  • 关键参数dim (维度)。例如 dim = c(3, 4, 2) 代表 3行 x 4列 x 2层。

代码演示:创建一个 3D 数组

# 创建一个 3行 x 4列 x 2层 的数组
#
my_array <- array(data = 1:24, dim = c(3, 4, 2))

# 打印结果:注意看 output 中的 ,,1 和 ,,2 (代表层级)
print(my_array)
, , 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

维度理解

想象一个 魔方 或者 一叠 Excel 表dim = c(3, 4, 2) 意思就是:有 2 页纸,每页纸上写着 3 行 4 列的数字。

第六部分:最灵活的容器——列表 (Lists)

5. 列表 (Lists):R 的万能收纳箱

列表是 R 中最灵活的数据结构。与向量和矩阵不同,列表允许每一个元素拥有不同的长度不同的模式 (Mode)。

为什么需要列表?

想象你要打包行李:

  1. 字符串:旅行主题 “Holiday”
  2. 数字:天数 7
  3. 矩阵:每天的行程表

只有 list() 能把它们装在一起。

# 创建一个包含字符、数字和矩阵的混合列表
meta_info <- "Island Study"
n_days <- 48
data_mat <- matrix(1:4, ncol=2)

# 打包
my_list <- list(title = meta_info, count = n_days, data = data_mat)

6. 列表的核心操作:[] vs [[]]

这是列表操作中最容易混淆的概念,请务必记清!

[] 单括号:提取子列表

  • 结果:依然是一个 List (盒子)。
  • 比喻:你从大箱子里拿出一个小盒子,糖还在盒子里。
#
res1 <- my_list[1] 
class(res1) # "list"

[[]] 双括号:提取内容

  • 结果原始数据类型 (字符/数字)。
  • 比喻:你把盒子打开,直接拿到了里面的
#
res2 <- my_list[[1]]
class(res2) # "character"

嵌套提取技巧my_list[[3]][1, 2] 表示先拿出第三个格子的矩阵,再取这个矩阵的第1行第2列。

第七部分:分类数据的处理

7. 因子 (Factor):名义变量的存储

R 使用 Factor 来存储分类变量 (Categorical Variables),如性别、种族、实验组别等。

  • 本质:因子在 R 内部其实是整数 (Integer),但贴上了标签 (Labels)
  • 陷阱:表面看是字,实际是数!

代码演示:从字符到因子

# 1. 原始字符向量
gender_char <- c("Male", "Female", "Female", "Male")

# 2. 转换为因子
#
gender_fac <- factor(gender_char)

# 3. 查看属性
print(gender_fac)
[1] Male   Female Female Male  
Levels: Female Male
# 输出: Male Female Female Male
# Levels: Female Male

终章:外部数据源接入与“体检”

1. 基础方案:读取 CSV/TXT (自带功能)

R 语言自带读取文本数据的函数,不需要安装任何包。

核心函数

  • CSV 文件 (逗号分隔):使用 read.csv()
  • TXT 文件 (Tab或空格分隔):使用 read.table()
# 读取 CSV 文件
# header = TRUE 表示第一行是标题
df_csv <- read.csv("data.csv", header = TRUE)

# 读取 TXT 文件
# sep = "\t" 代表 Tab 分隔
#
df_txt <- read.table("data.txt", header = TRUE, sep = "\t")

2. 进阶方案:Excel 与 Java

很多同学问:“读 .xlsx 文件是不是电脑必须装 Java?” 答案:看你用哪个包。

❌ 历史包袱:xlsx

  • 特点:依赖 Java 环境 (rJava)。
  • 缺点:如果你的电脑 Java 版本不对,或者没配环境变量,直接报错。这也是很多教程过时的原因。

✅ 现代方案:readxl 包 (推荐)

  • 特点:基于 C++ 编写,完全不需要 Java
  • 优点:轻量、快速、不报错。
library(readxl) 
# 读取 Excel,sheet = 1 指定第一页
df_excel <- read_excel("data.xlsx", sheet = 1)

3. 路径管理:绝对路径 vs 相对路径

关于“文件在哪里”,大家根据场景自由选择。

  • 方式 A:绝对路径 (Absolute Path)

  • 写法:"C:/Users/Jon/Desktop/Project/data.csv"

  • 评价:适合自己临时跑数,简单粗暴。但发给别人会报错(因为别人没有 Jon 这个用户)。

  • 方式 B:相对路径 (Relative Path)

  • 写法:"data.csv" (同级目录下)

  • 评价学术推荐。只要数据和代码在一起,发给谁都能跑。

📢 预告:Data Management

下节课我们将详细讲解 工作目录 (Working Directory)setwd() 函数,教大家如何优雅地管理几百个数据文件。

4. 关键步骤:数据“体检” (Check)

导入不报错 导入成功!你必须执行以下全套检查,防止数据“缺胳膊少腿”。

🩺 第一步:掐头去尾 (Head & Tail)

检查数据的开头和结尾,防止读取不完整。

head(df_excel, 5) # 看前 5 行:表头对了吗?
tail(df_excel, 5) # 看后 5 行:数据读全了吗?有没有多余的空行?

🩺 第二步:全身扫描 (Structure)

使用 str() 检查每个变量的类型。这是最重要的检查!

str(df_excel) 
# 重点看:
# 1. 也是 numeric (数字) 还是 chr (字符)?
#    (如果 Age 变成了 chr,说明里面混进了空格或文字)
# 2. 行数 (obs) 对不对?

🩺 第三步:统计概览 (Summary)

检查是否有异常值或缺失值。

summary(df_excel)
# 重点看:
# 1. Min/Max:有没有出现 -999 这种异常值?
# 2. NA's:有多少个缺失值?

课程总结与实战终章

1. 总结:R 语言数据结构全景图

回顾今天的课程,我们掌握了 R 语言存储数据的六大容器。记住它们的维度(Dimension)和同质性(Mode)区别。

同质结构 (Homogeneous)

所有元素必须是相同类型

  1. 向量 (Vectors)
    • 一维数组,最基本的存储单位。
  2. 矩阵 (Matrices)
    • 二维数组,通常用于数学运算。
  3. 数组 (Arrays)
    • 多维矩阵(N-dim),如 3D 数据块。

异质结构 (Heterogeneous)

允许包含不同类型的数据

  1. 列表 (Lists)
    • 最灵活的容器,有序的对象集合,什么都能装。
  2. 数据框 (Data Frames)
    • 矩阵的泛化,列与列之间可以不同(Excel 的亲兄弟)。

特殊存在因子 (Factors) —— 专门用于存储分类变量的向量,表面是字,底层是数。


实战技能:外部数据的接入

2. 基础方案:读取 CSV/TXT (自带功能)

R 语言自带读取文本数据的函数,不需要安装任何包。

核心函数

  • CSV 文件 (逗号分隔):使用 read.csv()
  • TXT 文件 (Tab或空格分隔):使用 read.table()