通过引用将类添加到data.frame列

时间:2018-08-29 20:12:16

标签: r data.table r-s3

我想为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创建。

0 个答案:

没有答案