我想为data.frame
(等等)创建一个子类。我想要一个功能
创建班级信息,然后删除班级信息。
df <- data.frame(x = 1:10)
我认为,这将是添加类的“ R认可”方式。和 添加然后删除该类,按预期工作,返回 未触碰的物体。
df2 <- df
class(df2$x) <- c("someclass", class(df2$x))
class(df2$x) <- class(df2$x)[class(df2$x) != "someclass"]
all.equal(df2, df)
#> [1] TRUE
但是如果我想通过引用更改对象,则此方法不起作用
因为class<-
似乎是data.table的副本:
add.class <- function(object) {
class(object$x) <- c("someclass", class(object$x))
return(invisible(object))
}
add.class(df)
class(df$x) # doesn't work
#> [1] "integer"
data.table
文档说明了设置属性的正确方法
通过引用使用的是setattr
,实际上,此功能确实可以
意向
add.class <- function(object) {
data.table::setattr(object$x, "class", c("someclass", class(object$x)))
return(invisible(object))
}
add.class(df)
class(df$x) # works!
#> [1] "someclass" "integer"
但是问题是,当使用相同的逻辑删除类时, 对象不能完全返回到先前的状态
remove.class <- function(object) {
data.table::setattr(object$x, "class", class(object$x)[class(object$x) != "someclass"])
return(invisible(object))
}
df <- data.frame(x = 1:10)
df2 <- data.table::copy(df)
add.class(df2)
remove.class(df2)
all.equal(df, df2) # Not equal!
#> [1] "Component \"x\": Attributes: < target is NULL, current is list >"
#> [2] "Component \"x\": target is numeric, current is integer"
all.equal(class(df$x), class(df2$x)) # But, equal classes??
#> [1] TRUE
该问题并非特定于data.table::setattr()
,因为常规
更改attr<-
属性时,class
函数具有相同的问题
df <- data.frame(x = 1:10)
df2 <- data.table::copy(df)
attr(df$x, "class") <- c("someclass", class(df$x))
attr(df$x, "class") <- class(df$x)[class(df$x) != "someclass"]
all.equal(df, df2)
#> [1] "Component \"x\": Attributes: < Modes: list, NULL >"
#> [2] "Component \"x\": Attributes: < Lengths: 1, 0 >"
#> [3] "Component \"x\": Attributes: < names for target but not for current >"
#> [4] "Component \"x\": Attributes: < current is not list-like >"
#> [5] "Component \"x\": target is integer, current is numeric"
我的猜测是class<-
所做的事情与attr<-
不同,并且
setattr()
。但是后来我意识到,只有当我改变时,它才会发生
列的类别。更改整个对象的类的工作原理是
预期的。
add.class <- function(object) {
data.table::setattr(object, "class", c("someclass", class(object)))
return(invisible(object))
}
remove.class <- function(object) {
data.table::setattr(object, "class", class(object)[class(object) != "someclass"])
return(invisible(object))
}
df <- data.frame(x = 1:10)
df2 <- data.table::copy(df)
add.class(df2)
remove.class(df2)
all.equal(df, df2)
#> [1] TRUE
这不是一个很大的问题,但确实使它痛苦不堪
进行正确的测试,因为我无法使用testthat::expect_equal()
作为单位
测试。
那么,通过以下方式更改data.frame
列的类的正确方法是什么
参考?
由reprex package(v0.2.0)于2018-08-29创建。