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 可代 TRUEF 可代 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)

九、第三章核心小结

  1. 原子型向量是基础:6 种类型,重点掌握双整型、整型(加 L)、字符型(加引号)、逻辑型,用 typeof() 查看类型;
  2. 属性扩展功能:名称属性(names())给元素贴标签,维度属性(dim())转矩阵 / 数组;
  3. 类决定处理方式:日期时间(POSIXct)存储秒数,因子(factor)处理分类数据,注意 stringsAsFactors = FALSE 避坑;
  4. 强制转换有规则:逻辑→数值→字符,手动用 as.系列 函数;
  5. 列表灵活,数据框常用:列表存混合类型,数据框是二维表格核心,加载 / 保存用 read.csv()/write.csv() 或 RDS 格式;
  6. 实战是关键:通过构建扑克牌数据集,理解 “如何用 R 对象存储现实数据”,为后续数据操作(洗牌、发牌)打下基础。

如果能独立完成 “扑克牌数据集” 的构建,恭喜你已经掌握了 R 数据存储的核心 —— 接下来的第四章将学习 “如何从数据框中提取和操作数据”(发牌、洗牌),敬请期待!

R 语言入门实战|第四章 R 的记号体系:从 “取数据” 到 “发牌洗牌”

posted @ 2025-09-15 22:07  yfceshi  阅读(15)  评论(0)    收藏  举报