打印包含 S4 对象列表列的 data.frame

Posted

技术标签:

【中文标题】打印包含 S4 对象列表列的 data.frame【英文标题】:printing a data.frame that contains a list-column of S4 objects 【发布时间】:2016-04-16 08:47:20 【问题描述】:

data.frame 具有 S4 对象的列表列时,打印它是否存在一般问题?还是我运气不好?

我在 git2r 包中遇到了这个问题,但维护者 Stefan Widgren 也从 Matrix 中指出了这个例子。我注意到如果通过dplyr::tbl_df() 发送对象,则可以打印该对象。我接受印刷没有提供太多关于 S4 对象的信息; 我只要求没有错误

更新的野心略高:data.frame-like 的品质能否保留?

library(Matrix)
library(dplyr)
m <- new("dgCMatrix")
isS4(m)
#> [1] TRUE
df <- data.frame(id = 1:2)
df$matrices <- list(m, m)
df
#> Error in prettyNum(.Internal(format(x, trim, digits, nsmall, width, 3L, : first argument must be atomic
tbl_df(df)
#> Source: local data frame [2 x 2]
#> 
#>      id
#>   (int)
#> 1     1
#> 2     2
#> Variables not shown: matrices (list).

## force dplyr to show the tricky column
tbl_df(select(df, matrices))
#> Source: local data frame [2 x 1]
#> 
#>                                                                      matrices
#>                                                                        (list)
#> 1 <S4:dgCMatrix, CsparseMatrix, dsparseMatrix, generalMatrix, dCsparseMatrix,
#> 2 <S4:dgCMatrix, CsparseMatrix, dsparseMatrix, generalMatrix, dCsparseMatrix,

## rawr points out that this does not error ... but loses the df quality
print.default(df)
#> $id
#> [1] 1 2
#> 
#> $matrices
#> $matrices[[1]]
#> 0 x 0 sparse Matrix of class "dgCMatrix"
#> <0 x 0 matrix>
#> 
#> $matrices[[2]]
#> 0 x 0 sparse Matrix of class "dgCMatrix"
#> <0 x 0 matrix>
#> 
#> 
#> attr(,"class")
#> [1] "data.frame"

【问题讨论】:

【参考方案1】:

另一种选择(可能产生比预期更大的后果)是:

library(Matrix)

format.list <- function(x, ...)  rep(class(x[[1]]), length(x)) 

m <- new("dgCMatrix")
df <- data.frame(id = 1:2)
df$matrices <- list(m, m)
df

##   id  matrices
## 1  1 dgCMatrix
## 2  2 dgCMatrix

【讨论】:

【参考方案2】:

这是一种获得不错打印结果的解决方法,但代价是覆盖data.frame(或者可以为打印目的制作副本):

library(Matrix)
m <- new("dgCMatrix")
df <- data.frame(id = 1:2)
df$matrices <- list(m, m)
df[] <- lapply(df, as.character)
df
#>   id                         matrices
#> 1  1 <S4 object of class "dgCMatrix">
#> 2  2 <S4 object of class "dgCMatrix">

感谢 @rawr,他最初在评论中提出建议。

【讨论】:

我不会称之为“解决方法”。这会破坏性地将第二列中的项目强制转换为完全不同的类别。数据框的列不应该包含列表。我怀疑它们也不应该包含 S4 构造函数。经典的容易失败的工作涉及 POSIXlt 分类向量。我知道它们不应该包含语言对象,例如函数或 R 表达式。我认为您应该放弃数据框作为目标并使用不同的容器类。

以上是关于打印包含 S4 对象列表列的 data.frame的主要内容,如果未能解决你的问题,请参考以下文章

使用 lapply 更改列表元素中列的格式

从列表中合并并平均每15个data.frames

如何更优雅地操作不同列表中的 data.frame 对象?

如何对 data.frame 列值求和?

替换数据帧列表中编号列的NA

更改 R 中数据框列表中的列名子集