以“ mpg”数据为例, 我编写了一些代码以非函数格式调用lsmeans函数,输出对我来说很好(如下所示)。
我尝试将代码修改为函数格式以生成相同的输出,但是在我编写的函数中无法识别数据的列。
我的函数报告的错误是:
Error in eval(predvars, data, env) : object 'cty' not found
library(rlang)
library(tidyverse)
library(dplyr)
library(multcompView)
library(lsmeans)
model = lm(cty ~ drv + class + drv:class,data=mpg)
anova(model)
marginal = lsmeans(model,~drv:class)
Pletters = multcomp::cld(marginal,
alpha=0.05,
Letters=letters,
adjust="tukey")
Pletters$.group=gsub(" ", "", Pletters$.group)
Pletters
library(rlang)
library(tidyverse)
library(dplyr)
library(multcompView)
library(lsmeans)
P_letters<-function(data, y, groupby, subgroupby){
model = lm(y ~ groupby + subgroupby + groupby:subgroupby,data=data)
anova(model)
marginal = lsmeans(model,~groupby:subgroupby)
Pletters = multcomp::cld(marginal,
alpha=0.05,
Letters=letters,
adjust="tukey")
Pletters$.group=gsub(" ", "", Pletters$.group)
Pletters
}
result<-mpg %>%
P_letters(y=cty, groupby=drv, subgroupby=class)
result
nalysis of Variance Table
Response: cty
Df Sum Sq Mean Sq F value Pr(>F)
drv 2 1878.81 939.41 136.6198 <2e-16 ***
class 6 804.78 134.13 19.5069 <2e-16 ***
drv:class 3 10.26 3.42 0.4974 0.6844
Residuals 222 1526.49 6.88
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
drv class lsmean SE df lower.CL upper.CL .group
r suv 12.0 0.791 222 9.58 14.4 a
4 pickup 13.0 0.456 222 11.60 14.4 a
4 suv 13.8 0.367 222 12.70 14.9 a
r 2seater 15.4 1.173 222 11.80 19.0 ab
f minivan 15.8 0.791 222 13.39 18.2 ab
r subcompact 15.9 0.874 222 13.21 18.6 ab
4 midsize 16.0 1.514 222 11.36 20.6 abc
4 compact 18.0 0.757 222 15.68 20.3 bc
f midsize 19.0 0.425 222 17.67 20.3 bc
4 subcompact 19.5 1.311 222 15.48 23.5 bcd
f compact 20.9 0.443 222 19.50 22.2 cd
f subcompact 22.4 0.559 222 20.65 24.1 d
4 2seater nonEst NA NA NA NA
f 2seater nonEst NA NA NA NA
r compact nonEst NA NA NA NA
r midsize nonEst NA NA NA NA
4 minivan nonEst NA NA NA NA
r minivan nonEst NA NA NA NA
f pickup nonEst NA NA NA NA
r pickup nonEst NA NA NA NA
f suv nonEst NA NA NA NA
Confidence level used: 0.95
Conf-level adjustment: sidak method for 21 estimates
P value adjustment: tukey method for comparing a family of 21 estimates
significance level used: alpha = 0.05
Error in eval(predvars, data, env) : object 'cty' not found
答案 0 :(得分:0)
某些R函数直接对用户编写的表达式进行操作,而不是对其求值。这是一个相当高级的概念,称为非标准评估(NSE),您可以在最近的tidy evaluation guide中进一步了解它。作为NSE的一个非常简短的示例,请考虑library()
函数:
library("tidyverse") # Works
a <- "tidyverse"
library( a )
# Error in library(a) : there is no package called ‘a’
如果library()
使用标准评估规则,则表达式a
会被评估为产生值"tidyverse"
,然后将其传递给library()
。但是,由于使用NSE,该函数直接与a
一起使用,而不是对其求值。
您要使用的功能属于同一伞下,需要特殊处理才能处理用户提供的表达式。 rlang
软件包提供了several mechanisms for this。特别是,我们将使用1)ensym()
捕获提供给函数的变量名; 2)expr()
组成一个未计算的表达式; 3)!!
运算符强制执行表达式求值。
P_letters <- function(data, y, groupby, subgroupby) {
## Compose a formula expression using user-supplied variable names
frml <- expr( !!ensym(y) ~ !!ensym(groupby) + !!ensym(subgroupby) +
!!ensym(groupby):!!ensym(subgroupby) )
## Pass the formula expression to lm()
model <- lm(frml,data=data)
print(anova(model))
## Compose and evaluate an expression for lsmean() call
lsm_expr <- expr( lsmeans(model,~!!ensym(groupby):!!ensym(subgroupby)) )
marginal <- eval(lsm_expr)
Pletters <- multcomp::cld(marginal, alpha=0.05,
Letters=letters, adjust="tukey")
Pletters$.group=gsub(" ", "", Pletters$.group)
Pletters
}
## This now produces the desired output
mpg %>% P_letters( y=cty, groupby=drv, subgroupby=class )