tbl_df is transformed as list in S4 class

2020-07-20 05:03发布

When I tried to use tbl_df in S4 classes, tbl_df slots seems to be transformed into list.

library('tibble')
setOldClass(c('tbl_df', 'tbl', 'data.frame'))
setClass(Class = 'TestClass', slots = c(name = 'character'), contains = 'tbl_df')

tmp1 <- new('TestClass', tibble(x = 1:5, y = 1, z = x ^ 2 + y), name = 'firsttest')
tmp1@.Data
[[1]]
[1] 1 2 3 4 5

[[2]]
[1] 1 1 1 1 1

[[3]]
[1]  2  5 10 17 26

Can I visit the tmp1@.Data just like a tbl_df object? like

tmp1@.Data
# A tibble: 5 x 3
      x     y     z
* <int> <dbl> <dbl>
1     1     1     2
2     2     1     5
3     3     1    10
4     4     1    17
5     5     1    26

标签: r s4 tibble
2条回答
家丑人穷心不美
2楼-- · 2020-07-20 05:15

S3 objects, just for simplification, are lists with an special attribute "class" which is used to call the correct generic function. print is a generic function that is being called when R outputs the tibble object.

library(tibble)
tb <- tibble(x = 1:5, y = 1, z = x ^ 2 + y)

dput(tb)
#structure(list(x = 1:5, y = c(1, 1, 1, 1, 1), z = c(2, 5, 10, 
#17, 26)), row.names = c(NA, -5L), class = c("tbl_df", "tbl", 
#"data.frame"))

attributes(tb)
#$`names`
#[1] "x" "y" "z"
#
#$row.names
#[1] 1 2 3 4 5
#
#$class
#[1] "tbl_df"     "tbl"        "data.frame"

When you create an S4 class using an S3 parent class, R only store the list on the .Data slot. R still keeps the attributes of the S3 objects but not in the .Data slot. When you print the TestClass, you get the tibble output plus the S4 slots. If just want the S3 object you can use as(object,"S3").

setOldClass(c('tbl_df', 'tbl', 'data.frame'))
setClass(Class = 'TestClass', slots = c(name = 'character'), contains = 'tbl_df')
tmp1 <- new('TestClass', tibble(x = 1:5, y = 1, z = x ^ 2 + y), name = 'firsttest1')
tmp1
#Object of class "TestClass"
## A tibble: 5 x 3
#      x     y     z
#* <int> <dbl> <dbl>
#1     1     1     2
#2     2     1     5
#3     3     1    10
#4     4     1    17
#5     5     1    26
#Slot "name":
#[1] "firsttest1"

attributes(tmp1)
#$`names`
#[1] "x" "y" "z"
#
#$row.names
#[1] 1 2 3 4 5
#
#$.S3Class
#[1] "tbl_df"     "tbl"        "data.frame"
#
#$name
#[1] "firsttest1"
#
#$class
#[1] "TestClass"
#attr(,"package")
#[1] ".GlobalEnv"

as(tmp1,"S3")
## A tibble: 5 x 3
#      x     y     z
#* <int> <dbl> <dbl>
#1     1     1     2
#2     2     1     5
#3     3     1    10
#4     4     1    17
#5     5     1    26
查看更多
三岁会撩人
3楼-- · 2020-07-20 05:16

Use contains = class(tibble()) in setClass(). More details see https://github.com/tidyverse/tibble/issues/618

查看更多
登录 后发表回答