【问题标题】:How can I control the output of a function in R (similar to lm)如何控制 R 中函数的输出(类似于 lm)
【发布时间】:2025-11-24 23:55:02
【问题描述】:

我正在 R 中创建一个自定义函数,该函数将几个不同的变量作为输入,并创建一个 data.frame、一个绘图和一些摘要统计信息,所有这些都存储在一个列表中。我只想在调用函数时打印出摘要统计信息,但在显式调用时让 plot 和 data.frame 可用。

我认为我想要的类似于lm() 的运作方式,但我不确定它是如何实现的。

当我打印lm 返回的对象时,我只得到$call$coefficients 的打印输出:

lm(mtcars$mpg ~ mtcars$cyl)

Call:
lm(formula = mtcars$mpg ~ mtcars$cyl)

Coefficients:
(Intercept)   mtcars$cyl  
     37.885       -2.876  

但显然在对lm 的函数调用中还有更多可用的功能。

lm(mtcars$mpg[1:3] ~ mtcars$cyl[1:3])$residuals
            1             2             3 
-1.280530e-15  1.280530e-15  8.365277e-31 

> unclass(lm(mtcars$mpg[1:3] ~ mtcars$cyl[1:3])

Call:
lm(formula = mtcars$mpg[1:3] ~ mtcars$cyl[1:3])

Coefficients:
    (Intercept)  mtcars$cyl[1:3]  
           26.4             -0.9  


> unclass(lm(mtcars$mpg[1:3] ~ mtcars$cyl[1:3]))
$coefficients
    (Intercept) mtcars$cyl[1:3] 
           26.4            -0.9 

$residuals
            1             2             3 
-1.280530e-15  1.280530e-15  8.365277e-31 

$effects
    (Intercept) mtcars$cyl[1:3]                 
  -3.741230e+01    1.469694e+00    1.810943e-15 

....

$call
lm(formula = mtcars$mpg[1:3] ~ mtcars$cyl[1:3])

$model
  mtcars$mpg[1:3] mtcars$cyl[1:3]
1            21.0               6
2            21.0               6
3            22.8               4

我查看了 lm 的代码,但我不太清楚发生了什么。

【问题讨论】:

  • 当您调用lm() 时,发送到终端的输出是通过调用print.lm() 产生的。 (它由 S3 通用函数 print 分派,该函数查找并找到类 lm 的对象的方法。)要查看 print.lm() 使用的代码,请键入 getAnywhere("print.lm")See also here 获取如何开发自己的自定义打印方法的示例。
  • 您应该查看lmstats:::print.lm 的代码,然后阅读?Methods,我认为(尽管我想不通)。
  • 你必须将你的列表变成一个 S3 对象并为它创建一个print 方法。我认为最好的解释例子是在这篇文章中。 cran.r-project.org/doc/contrib/Leisch-CreatingPackages.pdf。那篇文章展示了如何创建一个包,示例是一个类似于lm的简化对象
  • 要做到这一点,您需要了解一些有关 S3 类和方法的知识。这个答案会让你开始:*.com/q/6583265/602276
  • 另外,如果你想探索由 lm (或任何其他)创建的对象的结构,你可以使用str

标签: r


【解决方案1】:

调用lm 的结果是类属性设置为lm 的对象。这个类的对象有它们自己的打印方法(如果你想使用print.lm,你可以显式调用它)。您可以自己做类似的事情,只需设置函数返回的对象的类属性,然后编写自己的打印方法。这是一个例子:

my.func <- function(x, y, z){
    library(ggplot2)
    df <- data.frame(x, y, z)
    p <- ggplot(df, aes(x, y)) + geom_point()
    ds <- sapply(df, summary)

    op <- list(data = df, plot = p, summary = ds)
    class(op) <- 'my_list'
    op
}

print.my_list <- function(m){
    print(m$summary)
}

a <- my.func(1:5, 5:1, rnorm(5))
a
print.default(a)

因为列表a 的类属性设置为my_list,一旦你为它创建了一个打印方法,当你用那个类打印一个列表时,这个方法就会被使用。您可以通过显式调用print.default 查看整个对象。这里对 R 中的类有很好的解释:http://adv-r.had.co.nz/OO-essentials.html

【讨论】: