r - 在 R 函数中创建可重用对象的推荐方法
问题描述
假设我们有以下数据:
# simulate data to fit
set.seed(21)
y = rnorm(100)
x = .5*y + rnorm(100, 0, sqrt(.75))
我们还假设用户已经拟合了一个模型:
# user fits a lm
mod = lm(y~x)
现在假设我有一个 R 包,旨在对对象执行多项操作mod
。为简单起见,假设我们有两个函数,一个绘制数据,一个计算系数。但是,作为中介,假设我们要对数据执行一些操作(在本例中,加十)。
例子:
# function that adds ten to all scores
add_ten = function(model) {
data = model$model
data = data + 10
return(data)
}
# functions I defined that do something to the "add_ten" dataset
plot_ten = function(model) {
new_data = data.frame(add_ten(model))
x = all.vars(formula(model))[2]
y = all.vars(formula(model))[1]
ggplot2::ggplot(new_data, aes_string(x=x, y=y)) + geom_point() + geom_smooth()
}
coefs_ten = function(model) {
new_data = data.frame(add_ten(model))
coef(lm(formula(model), new_data))
}
(显然,这样做很愚蠢。实际上,我要执行的操作是多重插补,计算量很大)。
请注意,在上面的示例中,我必须调用该add_ten
函数两次,一次用于 plot_ten,一次用于 coefs_ten。这是低效的。
那么,现在我的问题是,在函数中创建可重用对象的最佳方法是什么?
当然,我可以创建一个放置在用户全局环境中的对象:
add_ten = function(model) {
# check for add_ten_data in the global environment
if (exists("add_ten_data", where = .GlobalEnv)) return(get("add_ten_data", envir = .GlobalEnv))
data = model$model
data = data + 10
# assign add_ten_data to the global environment
assign('add_ten_data', data, envir = .GlobalEnv)
return(data)
}
我很高兴这样做,但担心将某些东西放在用户环境中的“网络礼节”。如果用户在他们的环境中碰巧有一个名为“add_ten_data”的对象,那么还有一个潜在的问题。
那么,实现这一目标的最佳方法是什么?
提前致谢!
解决方案
您当然应该避免将对象写入全局环境。如果您发现必须在多个不同函数的顶部重复相同的计算量大的任务,这意味着您执行计算量大的任务为时已晚。
例如,您可以创建一个包含必要组件的 S3 类,以生成“廉价”图和“廉价”系数提取。它甚至具有通用调度的好处:
add_ten <- function(model) model$model + 10
lm_tens <- function(formula, data)
{
model <- if(missing(data)) lm(formula) else lm(formula, data = data)
structure(list(data = data.frame(add_ten(model)), model = model),
class = "tens")
}
plot.tens <- function(tens) {
x = all.vars(formula(tens$data))[2]
y = all.vars(formula(tens$data))[1]
ggplot2::ggplot(tens$data, ggplot2::aes(x = x, y = y)) +
ggplot2::geom_point() +
ggplot2::geom_smooth()
}
coef.tens = function(tens) {
coef(lm(formula(tens$model), data = tens$data))
}
所以现在我们只需要这样做:
set.seed(21)
y = rnorm(100)
x = .5*y + rnorm(100, 0, sqrt(.75))
mod <- lm_tens(y ~ x)
coef(mod)
#> (Intercept) x
#> 4.3269914 0.5775404
plot(mod)
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'
请注意,我们只需要在add_ten
这里调用一次。
推荐阅读
- http-post - angular 8 Http POST,内容类型为 application/x-www-form-urlencoded
- android - 为什么以下代码中缓存中的位图返回 null?
- javascript - 同步滚动 textarea 输入和突出显示容器
- html - 加载大数据时mat自动完成太慢
- sharepoint - 将值从 SharePoint 列表发送到 Power BI Desktop
- python - 如何操纵每个索引中的值?
- c# - 获取 microsoft 团队组的站点信息的问题
- r - 计算R中两条洛伦兹曲线(可能相交)之间的面积
- python - 为 tesserocr 运行 setup.py install ... 错误
- angular - 使用 Angular 7 以反应形式使用自定义选择组件