[1] "myclass" 很公平,我还没-6ren">
gpt4 book ai didi

r - 如何在 R 中创建不打印属性(不复制对象)的打印方法?

转载 作者:行者123 更新时间:2023-12-04 15:04:17 25 4
gpt4 key购买 nike

我在 R 中创建了一个自定义的 S3 对象,但是当我打印它时,属性也会被打印出来。例如:

x <- 1:3
x <- structure(x, class = "myclass")
print(x)
#> [1] 1 2 3
#> attr(,"class")
#> [1] "myclass"
很公平,我还没有添加 print方法。 SO和其他地方的许多答案都建议从对象中删除属性,然后将其打印出来,像这样(也将对象无形地返回以保持 print原始属性):
x <- 1:3
x <- structure(x, class = "myclass")

print.myclass <- function(x, ...) {
print(unclass(x), ...)
return(invisible(x))
}

print(x)
#> [1] 1 2 3
但是,这种方法会创建 x 的副本。 ,我不想那样。我们可以看到 tracemem() :
x <- 1:3
x <- structure(x, class = "myclass")
tracemem(x)
#> [1] "<0x558e1a9adcc8>"

print.myclass <- function(x, ...) {
print(unclass(x), ...)
return(invisible(x))
}

print(x)
#> tracemem[0x558e1a9adcc8 -> 0x558e1aa63918]: print print.myclass print
#> [1] 1 2 3
print不创建 x 的副本:
x <- 1:3
x <- structure(x, class = "myclass")
tracemem(x)
#> [1] "<0x557799ebeb88>"

print(x)
#> [1] 1 2 3
#> attr(,"class")
#> [1] "myclass"
Hadley 在他的高级 R 书中建议,可以使用 NextMethod()prevent creating a copy in a subset method .我花了一些时间思考如何在打印具有属性的 S3 对象时防止创建副本,但我无法弄清楚如何这样做。
事实上,我刚刚测试了打印 tibble并且还创建了一个副本:
z <- tibble::tibble(x = 1, y = 2)
tracemem(z)
#> [1] "<0x55e2aa368c48>"

print(z)
#> tracemem[0x55e2aa368c48 -> 0x55e2aa339e48]: lapply tbl_subset_row [.tbl_df [ do.call head.data.frame head as.data.frame tbl_format_setup.tbl tbl_format_setup_ tbl_format_setup format.tbl format writeLines print.tbl
#> # A tibble: 1 x 2
#> x y
#> <dbl> <dbl>
#> 1 1 2
但是一个 data.table没有:
z <- data.table::data.table(x = 1, y = 2)
tracemem(z)
#> [1] "<0x55d64b2bd310>"

print(z)
#> x y
#> 1: 1 2
所以我想这个问题是可以解决的,但我还没有弄清楚如何......
编辑:
好的,我在 print.data.frame 上做了一些阅读它通过转换 data.frame 解决了这个问题到 matrix然后打印这个矩阵。这是一个非常聪明的解决方案,我猜 data.table使用类似的东西。
然而,更一般地说,这不适用于其他类型的对象(例如,那些不能格式化为矩阵的对象)。拿这个:
z <- list(a = data.frame(a = 1, b = 2), b = data.frame(c = 3, d = 4))
z <- structure(z, class = "myotherclass")
tracemem(z)
#> [1] "<0x56298a95fd48>"

print(z)
#> $a
#> a b
#> 1 1 2
#>
#> $b
#> c d
#> 1 3 4
#>
#> attr(,"class")
#> [1] "myotherclass"

print.myotherclass <- function(x, ...) {
print(unclass(x), ...)
return(invisible(x))
}

print(z)
#> tracemem[0x56298a95fd48 -> 0x56298aaa58a8]: print print.myotherclass print
#> $a
#> a b
#> 1 1 2
#>
#> $b
#> c d
#> 1 3 4
在这种情况下你是怎么做的?

最佳答案

使用类似 print(x[seq_along(x)]) 的东西怎么样?在您的打印方法中?它避免了看起来的副本并且属性持续存在。

z <- list(a = data.frame(a = 1, b = 2), b = data.frame(c = 3, d = 4))
z <- structure(z, class = "myotherclass")
tracemem(z)

print.myotherclass <- function(x, ...) {
print(x[seq_along(x)])
return(invisible(x))
}

y <- print(z)
#> $`a`
#> a b
#> 1 1 2
#>
#> $b
#> c d
#> 1 3 4

attributes(y)
#> $`names`
#> [1] "a" "b"
#>
#> $class
#> [1] "myotherclass"

关于r - 如何在 R 中创建不打印属性(不复制对象)的打印方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66447164/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com