我正在尝试使用tidyeval(非标准评估)在“lm”周围编写一个函数。使用base R NSE,它可以工作:
lm_poly_raw <- function(df, y, x, degree = 1, ...){
lm_formula <-
substitute(expr = y ~ poly(x, degree, raw = TRUE),
env = list(y = substitute(y),
x = substitute(x),
degree = degree))
eval(lm(lm_formula, data = df, ...))
}
lm_poly_raw(mtcars, hp, mpg, degree = 2)
但是,我还没有弄清楚如何使用tidyeval
和rlang
来编写此函数。我假设substitute
应该被替换为enquo
,而eval则被!!
替换。 Hadley的Adv-R有一些提示,但我无法理解。
答案 0 :(得分:4)
以下是可能在未来的rlang中使用的公式构造函数:
const data = {
data: {
user: {
data: {
firstName: 'joe',
data: {surname: 'bloggs'}
}
},
message: 'this is a message'
}
};
const stripData = (data, root = true) => {
let result = {};
Object.keys(data).forEach(key => {
let value = data[key];
if (typeof value === 'object') {
value = stripData(value, false);
if (key === 'data') {
result = Object.assign(result, root ? {data: value} : value);
} else {
result[key] = value;
}
} else {
result[key] = value;
}
});
return result;
};
console.log(stripData(data));
棘手的部分是:
如果通过f <- function(x, y, flatten = TRUE) {
x <- enquo(x)
y <- enquo(y)
# Environments should be the same
# They could be different if forwarded through dots
env <- get_env(x)
stopifnot(identical(env, get_env(y)))
# Flatten the quosures. This warns the user if nested quosures are
# found. Those are not supported by functions like lm()
if (flatten) {
x <- quo_expr(x, warn = TRUE)
y <- quo_expr(y, warn = TRUE)
}
new_formula(x, y, env = env)
}
# This can be used for unquoting symbols
var <- "cyl"
lm(f(disp, am + (!! sym(var))), data = mtcars)
的不同层转发,LHS和RHS可能来自不同的环境。我们需要检查一下。
我们需要检查用户是否取消引用。 ...
并且不支持这些。 lm()
会使所有情况变得扁平化,并且如果找到某些情况,则可选择发出警告。