r - data.frame/tibble/data.table 中的自定义 S4 类
问题描述
我希望在data.frame
s (和/或 tibbles,data.tables,...)内部使用由我定义的 S4 类,类似于lubridate::period()
提供的内容。
例如,以下代码创建一个句点向量,将它们存储在 data.frame(在本例中为 tibble)中,提取一个值并再次访问该类...
tibble::tibble(
x = c(lubridate::period(120),
lubridate::period(2))
)
#> # A tibble: 2 x 1
#> x
#> <Period>
#> 1 120S
#> 2 2S
str(
tibble::tibble(
x = c(lubridate::period(120),
lubridate::period(2))
)$x[1]
)
#> Formal class 'Period' [package "lubridate"] with 6 slots
#> ..@ .Data : num 120
#> ..@ year : num 0
#> ..@ month : num 0
#> ..@ day : num 0
#> ..@ hour : num 0
#> ..@ minute: num 0
我想用典型的Person
课程来复制这个。
第一次(失败的)尝试如下所示:
.person <- setClass("Person",
slots = list(name = "character",
age = "numeric"))
person <- function(name, age) {
.person(name = name, age = age)
}
format.Person <- function(x, ...) {
paste0("<Person: ", x@name, " ", x@age, ">")
}
# create some instances
person("Alice", 123)
#> An object of class "Person"
#> Slot "name":
#> [1] "Alice"
#>
#> Slot "age":
#> [1] 123
## Fair enough, no proper "show" method implemented yet...
format(person("Alice", 123))
#> [1] "<Person: Alice 123>"
ppl <- c(person("Alice", 123),
person("Bob", 42))
ppl
#> [[1]]
#> An object of class "Person"
#> Slot "name":
#> [1] "Alice"
#>
#> Slot "age":
#> [1] 123
#>
#>
#> [[2]]
#> An object of class "Person"
#> Slot "name":
#> [1] "Bob"
#>
#> Slot "age":
#> [1] 42
## Now converting to data.frames
data.frame(x = ppl)
#> Error in unique.default(x, nmax = nmax) :
#> unique() applies only to vectors
tibble::tibble(x = ppl)
#> # A tibble: 2 x 1
#> x
#> <list>
#> 1 <Person>
#> 2 <Person>
data.table::data.table(x = ppl)
#> x
#> 1: <Person[2]>
#> 2: <Person[2]>
我最终想要的是有一些类似的东西:
tibble::tibble(x = ppl)
#> # A tibble: 2 x 1
#> x
#> <Person>
#> 1 <Alice, 123>
#> 2 <Bob, 42>
#>
解决方案
这不起作用的原因是因为data.frame
s(和类似的对象,如tibble
s)只能在它们的列中包含原子类型(即可以通过调用创建的东西vector
)。原子类型是“逻辑”、“整数”、“双”、“复杂”、“字符”、“原始”和“列表”。
实际上,这意味着您的类将必须包含这些原子类型之一(可能是“列表”),类似于setClass("onePerson",contains="list")
. 让每个插槽都是原子类型是不够的。如果您想强制列表具有正确类的正确组件,那么您可以使用validObject
方法来强制执行该操作。
可能会坚持使用不扩展原子类型的类定义,但您需要为类似的函数编写方法cbind2
并[
允许它与数据帧交互。
最后,您可以使您的person
类扩展data.frame
或扩展tibble
自身,但对列名和类型有限制。这与列表解决方案基本相同,因为数据框是列表。
推荐阅读
- typescript - TypeScript 在使用默认值时避免重复的类属性
- vb.net - 多个子事件在一个地方
- excel - Excel VBA ListRows.Add 将数据添加到单元格中,但不将行添加到表中
- windows - 如果它以数组中的任何字符串开头,则打印文本文件的行
- gdb - 在 Linux 上使用 Qt5 禁用位置无关代码和 ASLR?
- r - 多列模糊连接(多个)数据帧的最佳方法是什么?
- python - 删除 python 数据框中不需要的列
- javascript - 如何在 Wix Corvid 中将数据从后端返回到前端
- mongodb - 无法通过邮递员和使用 mongoose 将数组值对发布到 mongoDb
- python - 为什么 matplotlib FuncAnimation init_func 不起作用?