r - 如何使用可以与 c() 结合的 R vctrs 包构建对象
问题描述
我试图了解如何使用向量构建对象。我认为这很简单,但是当我在对象上使用 c() 时遇到了麻烦。
我们的对象有两个属性,x 和描述符,在这种情况下都是字符串(我的对象将具有不同类型的属性)。我们已经构建了一个构造函数 new_toy_vector。我还没有在这个例子中建立一个便利函数。
new_toy_vector <- function(
x = character(),
descriptor = character()) {
vctrs::vec_assert(x,character())
vctrs::vec_assert(descriptor, character())
vctrs::new_vctr(x,
descriptor = descriptor,
class = "toy_vector")
}
format.toy_vector <- function(x, ...) {
paste0(vctrs::vec_data(x)," is ", attr(x, "descriptor"))
}
obj_print_data.toy_vector <- function(x) {
cat(format(x), sep = "\n")
}
c(new_toy_vector("Hello", "Foo"), new_toy_vector("World", "Bar"))
#> Error: No common type for `..1` <toy_vector> and `..2` <toy_vector>.
由reprex 包(v0.3.0)于 2020-04-26 创建
然后我尝试用自己创建一个强制,除非由于某种原因没有定义默认方法:
> vec_ptype2.toy_vector.toy_vector <- function(x, y, ...) new_toy_vector()
> c(new_toy_vector("Hello", "Foo"), new_toy_vector("World", "Bar"))
Error: Can't convert <toy_vector> to <toy_vector>.
有什么我想念或误解的想法吗?为什么我不能合并示例中的两个对象?
解决方案
通常,当对象被子集时,属性不会被子集,这不是规则,“名称”属性是一个突出的例子,它不遵循这种做法。要创建行为类似于“名称”的属性,您必须跳过障碍,而{vctrs}旨在为您简化此类任务。
我们使用{vctrs}的方式是使用记录,我们不需要属性:
记录样式对象使用等长向量列表来表示对象的各个组件。最好的例子是 POSIXlt,它的底层是一个包含 11 个字段的列表,例如年、月和日。记录风格的类覆盖 length() 和子集方法来隐藏这个实现细节。
使用上面链接中的示例作为模板,我们可以实现您的案例:
new_toy_vector <- function(
value = character(),
descriptor = character()) {
vctrs::vec_assert(value,character())
vctrs::vec_assert(descriptor, character())
vctrs::new_rcrd(list(value = value, descriptor = descriptor), class = "toy_vector")
}
format.toy_vector <- function(x, ...) {
value <- vctrs::field(x, "value")
descriptor <- vctrs::field(x, "descriptor")
paste0('"', value," is ", descriptor, '"')
}
v1 <- new_toy_vector(
c("Hello", "World"),
c("Foo", "Bar"))
v2 <- c(
new_toy_vector("Hello", "Foo"),
new_toy_vector("World", "Bar"))
v1
#> <toy_vector[2]>
#> [1] "Hello is Foo" "World is Bar"
identical(v1, v2)
#> [1] TRUE
v2[2]
#> <toy_vector[1]>
#> [1] "World is Bar"
由reprex 包(v0.3.0)于 2021-01-23 创建
请注意,我们不需要创建强制方法,在这种情况下,记录的默认强制方法就足够了。
推荐阅读
- r - Tukey 检验结果箱线图
- ios - Cordova 应用程序启动器插件不适用于 iOS 以使用 uri 启动 iOS 应用程序
- spring - 在 Spring RestController 中验证查询参数的最佳实践
- heroku - 当本地主机上没有遇到问题时,为什么在部署时出现 Heroku 错误消息 H12 超时和“内部服务器错误”?
- node.js - 如果不满足某些先决条件,是否有可用于退出测试的 Jest 钩子?
- php - 为什么我无法通过 People API 接收我的地址
- reactjs - 在模拟器中测试反应原生 Firebase 推送通知
- algorithm - 指数大于 2 的偶数个数
- android - 如何使用 firebase ML Kit 识别条形码?
- python - 自动安装 SciPy