R 语言入门实战:第三章 R 对象 —— 从原子向量到扑克牌资料框
引言:为什么要学 R 对象?
在 R 语言中,“对象” 是数据的 “容器”—— 无论是单个数值、一组字符串,还是像 Excel 表格一样的结构化数据,都需要通过特定的 R 对象来存储。《R 语言入门与实践》第三章以 “创建一副虚拟扑克牌” 为实战案例,把 R 中核心的数据对象(原子型向量、矩阵、列表、数据框等)串联起来,让抽象的概念变得直观。
本章的核心目标是:掌握 R 中数据存储的基本单元,学会用数据框(数据科学最常用结构)构建结构化数据集。如果你想理解 “如何把现实中的数据(如扑克牌)转化为 R 可处理的格式”,这一章是关键 —— 毕竟,数据存储是数据分析的第一步!
一、原子型向量:R 对象的 “最小单元”
原子型向量是 R 中最简单的对象,特点是只能存储一种类型的数据(如纯数值、纯字符),是构建复杂对象的基础。R 支持 6 种原子型向量,重点掌握前 4 种即可。
1.1 4 种核心原子型向量(附代码示例)
| 类型 | 定义 | 创建方法 | 查看类型(typeof()) | 注意事项 |
|---|---|---|---|---|
| 双整型 | 默认数值类型(含小数) | 直接赋值,如 x <- 3.14 或 x <- 5 | "double" | 无需特殊标记,R 默认存储为双整型 |
| 整型 | 纯整数类型 | 数值后加 L,如 x <- 5L | "integer" | 必须加 L,否则会被视为双整型;L必须大写,否则会异常提示 |
| 字符型 | 文本数据 | 用双引号包裹,如 x <- "ace" | "character" | 引号不可省略,否则视为对象名 |
| 逻辑型 | 布尔值(真 / 假) | TRUE 或 FALSE(全大写) | "logical" | T 可代 TRUE,F 可代 FALSE,但不推荐 |
代码实战:创建不同类型的原子型向量
# 1. 双整型(默认数值)
double_vec 2) # 逻辑表达式结果也是逻辑型
typeof(logical_vec) # 输出:[1] "logical"
# 查看向量长度(length()函数)
length(char_vec) # 输出:[1] 4
1.2 冷门类型:复数与原始类型
- 复数类型:存储复数,如
c(1+2i, 3-4i),用typeof()查看为"complex",数据分析中极少用到; - 原始类型:存储原始字节,用
raw(n)创建长度为 n 的空原始向量,如raw(3),主要用于底层数据处理,新手可暂不关注。
二、属性:给向量 “加标签”
属性是附加在 R 对象上的 “元数据”(描述数据的数据),不改变对象本身的值,但能扩展对象功能。常用属性有名称属性和维度属性。
2.1 名称属性(给元素起名字)
用 names() 函数为向量元素添加名称,便于识别数据含义(比如给骰子的面加标签)。
代码实战:给骰子向量加名称
# 创建骰子向量(1-6)
die <- 1:6 # :生成连续整数向量
die # 输出:[1] 1 2 3 4 5 6
# 给每个面加名称(1对应"one",2对应"two")
names(die) <- c("one", "two", "three", "four", "five", "six")
die # 输出带名称的向量:
# one two three four five six
# 1 2 3 4 5 6
# 查看/删除名称属性
names(die) # 查看名称:[1] "one" "two" "three" "four" "five" "six"
names(die) <- NULL # 删除名称
die # 恢复为无名称向量
2.2 维度属性(把向量转成矩阵 / 数组)
用 dim() 函数给向量添加 “维度”,可将一维向量转为二维矩阵或多维数组。
代码实战:向量转矩阵
# 用之前的骰子向量(1-6)
die <- 1:6
# 给向量加维度:2行3列(dim()参数是长度为2的向量,代表行数、列数)
dim(die) <- c(2, 3)
die # 输出2×3矩阵:
# [,1] [,2] [,3]
# [1,] 1 3 5
# [2,] 2 4 6
die_matrix <- matrix(die, nrow = 2, byrow = TRUE)
die_matrix # 输出:
# [,1] [,2] [,3]
# [1,] 1 2 3
# [2,] 4 5 6
注意:R默认按“列优先”填充,若想按行填充,用matrix()函数,byrow=TRUE按行填充
三、复合对象:从一维到多维
当需要存储多维数据时,就需要矩阵、数组、列表、数据框这些复合对象。其中,矩阵(二维)、数组(多维) 仍要求所有元素类型一致,而列表和数据框支持混合类型,会在下面详细介绍。
3.1 矩阵(matrix):二维数值容器
矩阵是 “带维度的向量”,仅存储一种类型数据,常用于线性代数运算。创建用 matrix() 函数,核心参数:
data:输入向量;nrow/ncol:行数 / 列数(二选一,另一个会自动计算);byrow:是否按行填充(默认FALSE,按列填充)。
代码实战:创建扑克牌花色矩阵
# 4种花色,每种花色3张牌(简化示例)
suit <- c("spades", "hearts", "diamonds", "clubs")
cards <- rep(suit, each = 3) # rep()重复元素,each=3表示每个元素重复3次
# [1] "spades" "spades" "spades" "hearts"
# [5] "hearts" "hearts" "diamonds" "diamonds"
# [9] "diamonds" "clubs" "clubs" "clubs"
# 创建3行4列矩阵(3张牌/花色,4种花色)
suit_matrix <- matrix(cards, nrow = 3, byrow = TRUE)
colnames(suit_matrix) <- suit # 给列加名称(花色)
suit_matrix # 输出:
# spades hearts diamonds clubs
# [1,] "spades" "hearts" "diamonds" "clubs"
# [2,] "spades" "hearts" "diamonds" "clubs"
# [3,] "spades" "hearts" "diamonds" "clubs"
当然也存在rownames()函数可以动手试试;
3.2 数组(array):多维容器
数组是矩阵的扩展,支持 3 维及以上,创建用 array() 函数,核心参数:
- data:数组中的数据,通常是一个向量(原子型向量,如数值、字符等)。
- dim:维度(行数、列数、层数),是整数向量,长度等于数组的维度数(如长度 2 表示二维数组,即矩阵;长度 3 表示三维数组,如
c(2,3,2)表示 2 行 3 列 2 层)。 dimnames:数组的 “维度名称”(可选),数组的每个维度添加名称标签(如行名、列名、层名),增强可读性,是一个列表,列表长度需与dim的长度一致(每个列表元素对应一个维度的名称)。
代码实战:创建 3 维数组(模拟 2 副骰子)
# 2副骰子,每副2行3列
dice_array <- array(
data = rep(1:6, 2), # 数据:2副骰子的6个面
dim = c(2, 3, 2), # 维度:2行3列2层(2副)
dimnames = list(
c("row1", "row2"), # 行名称
c("col1", "col2", "col3"), # 列名称
c("dice1", "dice2") # 层名称(2副骰子)
)
)
# 查看数组
dice_array
# , , dice1
# col1 col2 col3
# row1 1 3 5
# row2 2 4 6
#
# , , dice2
# col1 col2 col3
# row1 1 3 5
# row2 2 4 6
四、类(Class):给对象 “分类”
类是 R 的 “对象类型标签”,决定了 R 如何处理该对象(如打印格式、函数适用规则)。第三章重点讲日期时间类和因子类。
4.1 日期时间类(POSIXct)
R 用 POSIXct 类存储日期时间,本质是 “自 1970-01-01 00:00:00 UTC 起的秒数”(双整型),但显示为人类可读的格式。
代码实战:创建并查看日期时间
# 获取当前系统时间(默认POSIXct类)
current_time <- Sys.time()
current_time # 输出:[1] "2025-09-12 10:24:02 CST"
typeof(current_time) # 本质是双整型:[1] "double"
class(current_time) # 类标签:[1] "POSIXct" "POSIXt"
# R使用包含单个元素的双整型向量生成一个事件对象
# 可以使用unclass()将事件对象current_time的class属性移除,看到该对象的本来面目
unclass(now) # 输出:1757643843
# 同事也可以定义一个双整型向量,并且赋给类型"POSIXct" "POSIXt"
# R会根据赋给的类型将时间转换成用户可以理解的字符串形式
mil <- 1757643843
class(mil) <- c("POSIXct", "POSIXt")
mil # 输出: 2025-09-12 10:24:02 CST
# 手动创建日期时间(用as.POSIXct())
birthday <- as.POSIXct("2000-01-01 08:00:00", tz = "Asia/Shanghai")
birthday # 输出:[1] "2000-01-01 08:00:00 CST"
4.2 因子类(factor):处理分类数据
因子用于存储分类变量(如性别、花色),会自动生成 Levels(类别集合),但新手容易踩坑 ——R 默认将字符型向量转为因子,可能导致后续分析错误(如数值计算混乱)。
代码实战:创建因子与避坑
# 1. 自动转因子(默认行为,需注意)
suit_factor <- factor(c("spades", "hearts", "spades"))
suit_factor # 输出含Levels的因子:
# [1] spades hearts spades
# Levels: hearts spades
# 2. 查看因子的Levels
levels(suit_factor) # 输出:[1] "hearts" "spades"
# 3. 避坑:创建数据框时禁用自动转因子
# 错误示例:字符型自动转因子
bad_df <- data.frame(suit = c("spades", "hearts"))
str(bad_df) # 输出:'data.frame': 2 obs. of 1 variable: $ suit: Factor w/ 2 levels "hearts","spades": 2 1
# 正确示例:用stringsAsFactors = FALSE禁用
good_df <- data.frame(
suit = c("spades", "hearts"),
stringsAsFactors = FALSE # 关键参数!
)
str(good_df) # 输出:'data.frame': 2 obs. of 1 variable: $ suit: chr "spades" "hearts"
对于自动转因子的行为也不能一概而论,在输入函数时,也可以查看是否默认禁用或者开启的,再根据实际情况添加相应参数,如图现在的data.frame()默认是禁用的

五、强制转换:R 的 “数据类型妥协规则”
当向量中混合不同类型数据时,R 会自动强制转换为 “兼容性最高” 的类型,规则如下(优先级从低到高):逻辑型 → 数值型(双整型 / 整型) → 字符型
5.1 自动强制转换(示例)
# 1. 逻辑型 + 数值型 → 数值型(TRUE=1,FALSE=0)
mix1 <- c(TRUE, 3, FALSE)
mix1 # 输出:[1] 1 3 0
typeof(mix1) # 输出:[1] "double"
# 2. 数值型 + 字符型 → 字符型
mix2 <- c(123, "ace", 456)
mix2 # 输出:[1] "123" "ace" "456"
typeof(mix2) # 输出:[1] "character"
5.2 手动强制转换(as 系列函数)
用 as.类型() 函数手动转换,注意转换失败会返回 NA。
# 1. 字符型转数值型(仅纯数字字符可转)
char_num <- c("10", "20", "30")
as.numeric(char_num) # 输出:[1] 10 20 30
# 2. 字符型转逻辑型(仅"TRUE"/"FALSE"可转)
char_log <- c("TRUE", "FALSE", "abc")
as.logical(char_log) # 输出:[1] TRUE FALSE NA("abc"转失败)
# 3. 数值型转字符型
num_char <- as.character(1:5)
num_char # 输出:[1] "1" "2" "3" "4" "5"
六、列表(list):R 的 “万能容器”
列表是唯一能存储不同类型元素的一维对象,可包含向量、矩阵、甚至另一个列表,灵活性极高,常用于存储复杂数据(如模型结果)。
6.1 创建列表与提取元素
- 创建:用
list()函数,元素可任意类型; - 提取:
- 双中括号
[[ ]]:提取单个元素(返回元素本身类型); - 单中括号
[ ]:提取子列表(返回列表类型); - 美元符号
$:按名称提取元素(最常用)。
- 双中括号
代码实战:创建 “单张扑克牌” 列表
# 创建列表:包含牌面(字符)、花色(字符)、点数(数值)、是否为大牌(逻辑)
card_list <- list(
face = "ace",
suit = "hearts",
value = 1,
is_royal = FALSE,
stats = c(1, 3, 5) # 甚至可以包含向量
)
# 查看列表
card_list
# $face
# [1] "ace"
#
# $suit
# [1] "hearts"
#
# $value
# [1] 1
#
# $is_royal
# [1] FALSE
#
# $stats
# [1] 1 3 5
# 提取元素
card_list$face # 按名称提取:[1] "ace"
card_list[[2]] # 按位置提取(第2个元素):[1] "hearts"
card_list[["value"]] # 按名称+双中括号提取:[1] 1
card_list[1:2] # 提取子列表(第1-2个元素):list(face="ace", suit="hearts")
七、数据框(data.frame):数据科学的 “核心结构”!!!
数据框是二维表格型结构,每行是一个观测(如一张牌),每列是一个变量(如牌面、花色、点数),特点是:
- 每列是同类型数据(原子型向量);
- 不同列可不同类型(如字符型、数值型);
- 完全对应 Excel 表格,是数据分析的 “标配”。
7.1 创建数据框(结合扑克牌案例)
# 1. 准备列向量(牌面、花色、点数)
face <- c("king", "queen", "jack", "ten", "ace")
suit <- rep("spades", 5) # 5张黑桃牌
value <- c(13, 12, 11, 10, 1)
# 2. 创建数据框(禁用自动转因子)
poker_df <- data.frame(
face = face,
suit = suit,
value = value,
stringsAsFactors = FALSE # 必加!避免字符转因子
)
# 3. 查看数据框
head(poker_df) # 查看前5行(全部数据)
# face suit value
# 1 king spades 13
# 2 queen spades 12
# 3 jack spades 11
# 4 ten spades 10
# 5 ace spades 1
str(poker_df) # 查看数据结构
# 'data.frame': 5 obs. of 3 variables:
# $ face : chr "king" "queen" "jack" "ten" ...
# $ suit : chr "spades" "spades" "spades" "spades" ...
# $ value: num 13 12 11 10 1
7.2 加载与保存数据框
实际分析中,数据框常从外部文件(如 CSV)加载,或保存为文件供后续使用。
代码实战:加载 CSV 与保存数据
# 1. 保存数据框为CSV文件(row.names=FALSE避免多余行号)
write.csv(
x = poker_df,
file = "poker.csv", # 保存路径(默认在工作目录)
row.names = FALSE # 关键!避免保存行号
)
# 2. 加载本地CSV文件(stringsAsFactors=FALSE禁用转因子)
loaded_poker <- read.csv(
file = "poker.csv",
stringsAsFactors = FALSE
)
head(loaded_poker) # 与原数据框一致
# 3. 加载R特有格式(RDS,适合单个对象)
saveRDS(poker_df, file = "poker.rds") # 保存
loaded_rds <- readRDS("poker.rds") # 加载
# 4. 查看工作目录(确认文件位置)
getwd() # 输出当前工作目录路径
# setwd("C:/Users/你的用户名/Documents") # 若需修改工作目录
八、实战:从零构建完整扑克牌数据集(52 张牌)
结合本章所有知识点,手动生成一副完整的扑克牌(4 种花色 ×13 种牌面),加深对 R 对象的理解。
# 步骤1:定义基础向量
# 13种牌面(按点数从大到小)
face <- c("king", "queen", "jack", "ten", "nine", "eight", "seven",
"six", "five", "four", "three", "two", "ace")
# 4种花色
suit <- c("spades", "hearts", "diamonds", "clubs")
# 对应点数(king=13,ace=1)
value <- c(13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
# 步骤2:生成所有组合(4×13=52张牌)
# expand.grid()生成所有花色×牌面的组合
deck <- expand.grid(
face = face,
suit = suit,
stringsAsFactors = FALSE
)
# 步骤3:添加点数列(每个花色重复13个点数)
deck$value <- rep(value, times = length(suit))
# 步骤4:调整行顺序(按花色分组,同花色内按牌面顺序)
deck <- deck[order(deck$suit, factor(deck$face, levels = face)), ]
rownames(deck) <- 1:nrow(deck) # 重置行号
# 步骤5:查看最终数据集
head(deck, 10) # 查看前10行(黑桃牌)
# face suit value
# 1 king spades 13
# 2 queen spades 12
# 3 jack spades 11
# 4 ten spades 10
# 5 nine spades 9
# 6 eight spades 8
# 7 seven spades 7
# 8 six spades 6
# 9 five spades 5
# 10 four spades 4
# 保存数据集供后续使用(项目2:玩扑克牌)
write.csv(deck, "deck.csv", row.names = FALSE)
九、第三章核心小结
- 原子型向量是基础:6 种类型,重点掌握双整型、整型(加 L)、字符型(加引号)、逻辑型,用
typeof()查看类型; - 属性扩展功能:名称属性(
names())给元素贴标签,维度属性(dim())转矩阵 / 数组; - 类决定处理方式:日期时间(POSIXct)存储秒数,因子(factor)处理分类数据,注意
stringsAsFactors = FALSE避坑; - 强制转换有规则:逻辑→数值→字符,手动用
as.系列函数; - 列表灵活,数据框常用:列表存混合类型,数据框是二维表格核心,加载 / 保存用
read.csv()/write.csv()或 RDS 格式; - 实战是关键:通过构建扑克牌数据集,理解 “如何用 R 对象存储现实数据”,为后续数据操作(洗牌、发牌)打下基础。
如果能独立完成 “扑克牌数据集” 的构建,恭喜你已经掌握了 R 数据存储的核心 —— 接下来的第四章将学习 “如何从数据框中提取和操作数据”(发牌、洗牌),敬请期待!

浙公网安备 33010602011771号