Tidyverse使用列子集作为预测器获取lm()残差的方法,但将所有列保留在输出中
我有一些数据如下: dat=tibble var1=代表“A”和“B”,各=5 ,var2=rnorm10 ,var3=rnorm10 ,var4=rnorm10 ,var5=rnorm10 通过显式命名lm公式中要使用的列,我可以得到我想要的:Tidyverse使用列子集作为预测器获取lm()残差的方法,但将所有列保留在输出中,r,tidyverse,R,Tidyverse,我有一些数据如下: dat=tibble var1=代表“A”和“B”,各=5 ,var2=rnorm10 ,var3=rnorm10 ,var4=rnorm10 ,var5=rnorm10 通过显式命名lm公式中要使用的列,我可以得到我想要的: dat %>% #dat has columns: var1 through var5 dplyr::group_by(var1) %>% dplyr::mutate( resids = resid(
dat %>%
#dat has columns: var1 through var5
dplyr::group_by(var1) %>%
dplyr::mutate(
resids = resid(lm( var2 ~ var3 + var4 ))
)
但实际上我的真实数据集中有很多列,我将使用的列的数量和名称会有所不同。我知道那些我不想要的名字,所以我想这样行:
dat%>%
dat有以下列:var1到var5
dplyr::group_byvar1%>%
dplyr::突变
剩余=剩余
公式=var2~。
,数据=.%>%选择-var1,-var5
但这似乎不起作用。有什么建议吗?既然您知道不在模型右侧的变量,一种选择是将这些名称放入向量中,然后为lm构建公式。这意味着在管道链之外多做一步 构建公式是一种相对常见的方法,例如,生成拟合模型的函数。我写了一篇博客来展示这种方法 在本例中,您可以根据不需要的变量,将模型中需要的变量的名称作为字符向量提取出来
modvars = dat %>%
select(-var1, -var5, -var2) %>%
names()
modvars
[1] "var3" "var4"
将变量粘贴在一起后,可以使用as.formula构建模型拟合的公式。这就是它的样子:
as.formula(paste("var2 ~", paste(modvars, collapse = "+") ) )
var2 ~ var3 + var4
更容易的是,通过@BenBolker的评论重新制定方法
reformulate(modvars, response = "var2")
var2 ~ var3 + var4
您可以在管道链外部构建此对象,也可以将其直接放入链中。这里我做后者
dat %>%
dplyr::group_by(var1) %>%
dplyr::mutate(
resids = resid(lm(
formula = reformulate(modvars, response = "var2") )
)
)
# A tibble: 10 x 6
# Groups: var1 [2]
var1 var2 var3 var4 var5 resids
<chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 A 0.0792 0.265 0.637 -0.106 0.386
2 A -0.845 0.386 1.20 1.55 -0.232
3 A 0.465 1.12 -0.750 0.726 -0.141
4 A -0.365 -1.19 0.174 0.347 -0.126
5 A 0.395 -0.0515 -0.464 -0.0934 0.112
6 B -2.83 -0.0664 -0.0958 0.588 -1.99
7 B 0.383 1.16 -0.339 0.492 0.838
8 B 1.35 0.270 2.40 0.626 -0.512
9 B 0.620 -1.33 1.32 -0.148 0.688
10 B 0.664 -0.0487 0.426 -0.158 0.973
残差与您的原始方法相匹配,您在其中写出了公式:
dat %>%
#dat has columns: var1 through var5
dplyr::group_by(var1) %>%
dplyr::mutate(
resids = resid(lm( var2 ~ var3 + var4 ))
)
# A tibble: 10 x 6
# Groups: var1 [2]
var1 var2 var3 var4 var5 resids
<chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 A 0.0792 0.265 0.637 -0.106 0.386
2 A -0.845 0.386 1.20 1.55 -0.232
3 A 0.465 1.12 -0.750 0.726 -0.141
4 A -0.365 -1.19 0.174 0.347 -0.126
5 A 0.395 -0.0515 -0.464 -0.0934 0.112
6 B -2.83 -0.0664 -0.0958 0.588 -1.99
7 B 0.383 1.16 -0.339 0.492 0.838
8 B 1.35 0.270 2.40 0.626 -0.512
9 B 0.620 -1.33 1.32 -0.148 0.688
10 B 0.664 -0.0487 0.426 -0.158 0.973
这里的问题不是子专题,而是对主题的混淆。在公式中。这是指变量还是指数据 与此相关的还有其他问题,即选择。您应该使用dodata={.}%>%subset-var1,var5,而不是您所拥有的,或者简单地使用data=subset.,-var1,-var5。如何解决这个问题: 使用nest+unest 通过嵌套,分组变量将自动从数据中删除:
dat %>%
nest_by(var1) %>%
mutate(resid = list(resid(lm(formula = var2 ~ .-var5, data = data))))%>%
unnest(c(data, resid))
使用分组+汇总
您的代码无效,因为特殊符号无效。在数据中=.%>%select-var1,-var5实际上是尚未分组的输入数据。在dplyr 1.0.0之后,cur_data解决了这个问题,它给出了当前组的当前数据,不包括分组变量
dat %>%
group_by(var1) %>%
mutate(
resids = resid(lm(var2 ~ ., cur_data() %>% select(-var5)))
)
请注意,我使用select-var5而不是selectivar1,-var5,因为cur_数据排除了分组变量,即var1,因此selectivar1,-var5将得到一个错误:
无法子集不存在的列
作为@IRTFM注释,您还可以在传递给lm之前选择变量。记住使用当前数据而不是
在这里,您仍然不需要在select中排除var1,因为无法排除分组变量。dat在哪里?您能将dputdat和add添加到问题中吗?@Duck我在开始时添加了代码来生成一个虚拟数据集。@IRTFM因为,正如标题中所述,我想在输出中保留所有原始列,只需将剩余列添加为一个新列。是的,这是可行的,但不是很tidyverse风格,与接受的答案相反。@IRTFM无错误并不意味着它是正确的……请检查lm的输出。在传递到lm后,group_by毫无意义,因此var1仍然包含在模型中,并且有一个系数估计值。不要忘记重新格式化。。。reformulatemodvars,response=var2I我认为我从未使用过reformulate@BenBolker,这看起来非常棒。谢谢
dat %>%
group_by(var1) %>%
mutate(
resids = resid(lm(var2 ~ ., cur_data() %>% select(-var5)))
)
dat %>%
group_by(var1) %>%
select(-var5) %>%
mutate(
resids = resid(lm(var2 ~ ., cur_data()))
)