S3 R语言数据类型6:S3系统与原子向量
在 R 语言中,S3 向量的本质是:通过 S3 面向对象系统增强的原子向量。它们是基础原子向量(如数值型、字符型等)与 S3 类属性结合的结果,赋予向量领域特定的行为和语义。
1.面向对象编程(OOP)
There is an important difference in philosophy between S(and hence R) and the other main statistical systems. In S a statistical analysis is normally done as a series of steps, with intermediate results being stored in objects.
- R语言中的面向对象编程(Object-Oriented Programming, OOP)是一种重要的编程范式,它将对象作为程序的基本单元,通过将数据和操作封装(encapsulate)在对象中,提高了代码的可读性、可维护性和可扩展性。
- R语言支持多种面向对象编程模型,主要包括S3、S4和R6。
1.1 S3 模型
-
S3是R语言中最简单、最灵活的面向对象模型。
-
它基于泛型函数(generic functions)的概念,通过UseMethod()函数来实现方法的调度。
-
S3模型的实现方式相对简单,但缺乏严格的类定义和类型检查。
-
泛型函数(generic function)是一种编程范式,它允许我们为不同的数据类型编写相同的函数接口。
-
泛型函数的工作原理是:它们会根据传入的实际参数类型调用相应的方法。这意味着你可以为不同的类或数据结构定义相同名称的函数,但是它们的行为取决于传入的对象类型。
-
类和对象:在S3中,类是通过
class()函数分配给对象的。例如,可以将一个列表分配为某个类的对象:
person <- list(name = "Alice", age = 30) # 1. 创建基础列表
class(person) <- "Person" # 2. 添加类属性
- 方法:S3中的方法是通过
function.classname的形式命名的。例如,可以为print函数创建一个针对Person类的自定义方法:
print.Person <- function(p) {
cat("Name:", p$name, "\n") # 输出姓名
cat("Age:", p$age, "\n") # 输出年龄
}
person# 直接调用对象名(隐式调用 print)
Name: Alice
Age: 30
当调用print(person)时,R会根据person的类属性"Person"来选择并调用print.Person函数。
- 继承:S3支持基于类的继承。例如,可以定义一个
Student类继承自Person类,并添加新的属性或方法:
# 创建学生对象
student <- list(name = "Bob", age = 20, major = "Mathematics")
# 设置类层级:Student 继承自 Person
class(student) <- c("Student", "Person")
# 定义 Student 专属的打印方法
print.Student <- function(s) {
print.Person(s) # 调用父类方法
cat("Major:", s$major, "\n") # 添加子类专属信息
}
1.2 S4 模型
S4是R语言中更正式、更严格的面向对象模型。它提供了更严格的类定义和类型检查机制,适合用于大型软件项目。
1.3 R6 模型
R6是R语言中一个较新的面向对象模型,它提供了更接近传统OOP语言(如Python和Java)的特性,包括封装、继承和公有/私有方法。
关于面向对象的编程之后会更进一步学习……
2. 四个重要的 S3 向量
2.1 因子 factor
类别(名义型)变量和有序类别(有序型)变量在R中称为因子(factor)。
factor是一种只能包含预定义值的向量。它用于存储分类数据。
factor建立在整数向量之上,具有两个属性:一个 class 属性,值为“factor”,这使得它与普通的整数向量表现不同;以及 levels 属性,它定义了允许值的集合。
x <- factor(c("a", "b", "b", "a"))#创建因子 x
#factor()函数将其转换为因子类型,并自动提取唯一值作为水平(levels),默认按字母顺序排列。
x
- a
- b
- b
- a
- 'a'
- 'b'
typeof(x) # 检查数据类型:typeof(x)输出: b"integer"
attributes(x)#检查属性:attributes(x)
‘integer’
-
$levels
-
- 'a'
- 'b'
$class
- 'factor'
有序因子(ordered factor)
# 创建有序因子
grade <- ordered(c("b", "b", "a", "c"), # 输入数据
levels = c("c", "b", "a") # 显式定义水平顺序
)
# 输出结果
grade
- b
- b
- a
- c
- 'c'
- 'b'
- 'a'
2.2 日期(日精度)Date
# 获取当前日期
today <- Sys.Date()
today
# 查看数据类型
typeof(today)
#> [1] "double"
# 查看对象属性
attributes(today)
#> $class
#> [1] "Date"
‘double’
$class = ‘Date’
# 将字符串转换为日期对象
# 所有 R 日期对象存储为 自 1970-01-01 起的天数(称为 Unix 纪元)
date <- as.Date("2025-08-01")
# 去除类属性查看原始数值
unclass(date)
20301
日期值通常以字符串的形式输入到R中,然后转化为以数值形式存储的日期变量。函数as.Date()用于执行这种转化。
2.3 日期时间(具有秒或亚秒精度)POSIXct
- base R 提供了两种存储日期时间信息的方式,POSIXct 和 POSIXlt。
- “POSIX” 是 Portable Operating System Interface 的缩写,它是一系列跨平台标准。
- “ct” 代表日历时间(C 语言中的 time_t 类型),而“lt” 代表本地时间(C 语言中的 struct tm 类型)。
# 创建 POSIXct 时间对象
now_ct <- as.POSIXct("2025-08-01 22:00", tz = "UTC")
# 显示时间对象
now_ct
#> [1] # ISO格式 + 时区
# 检查底层存储类型
typeof(now_ct)
#> [1] "double" # 双精度浮点数
# 查看对象属性
attributes(now_ct)
#> $class
#> [1] "POSIXct" "POSIXt" # 类属性
#>
#> $tzone
#> [1] "UTC" # 时区属性
[1] "2025-08-01 22:00:00 UTC"
‘double’
-
$class
-
- 'POSIXct'
- 'POSIXt'
$tzone
- 'UTC'
# 转换为北京时区
beijing_time <- structure(now_ct, tzone = "Asia/Shanghai")
beijing_time
[1] "2025-08-02 06:00:00 CST"
2.4 持续时间 difftime
- 持续时间,表示日期或日期时间对之间的时间量,存储在 difftimes 中。
- Difftimes 基于 doubles 构建,并具有一个
units属性。
# 创建以周为单位的时间差
one_week_1 <- as.difftime(1, units = "weeks")
one_week_1
#> Time difference of 1 weeks
# 创建以天为单位的时间差
one_week_2 <- as.difftime(7, units = "days")
one_week_2
#> Time difference of 7 days
# 检查数据类型
typeof(one_week_1) # "double"
typeof(one_week_2) # "double"
# 查看对象属性
attributes(one_week_1)
#> $class
#> [1] "difftime"
#>
#> $units
#> [1] "weeks"
attributes(one_week_2)
#> $class
#> [1] "difftime"
#>
#> $units
#> [1] "days"
Time difference of 1 weeks
Time difference of 7 days
‘double’
‘double’
-
$class
- 'difftime' $units
- 'weeks'
-
$class
- 'difftime' $units
- 'days'
8320

被折叠的 条评论
为什么被折叠?



