Поскольку вы работать точно такой же регрессии для каждой группе, вам может быть проще просто определить вашу модель регрессии как function()
, а затем выполнить его для каждой группы, используя mutate
.
model<- function(y,x){
a<- y + x
if(length(which(!is.na(a))) <= 2 ){
return(rep(NA, length(a)))
} else {
m<- lm(y ~ x, na.action = na.exclude)
return(residuals(m))
}
}
Обратите внимание, что первая часть этой функции застраховаться от каких-либо сообщений об ошибках выскакивают в случае, если ваш регрессия работать на группе с менее чем ноль степеней свободы (это может быть в случае, если у вас есть a dataframe
с несколькими переменными группировки со многими levels
или многочисленными независимыми переменными для вашей регрессии (например, lm(y~ x1 + x2)
), и не может позволить себе проверять каждый из них при достаточных наблюдениях, не связанных с NA).
Так что ваш пример можно переписать следующим образом:
iris %>% group_by(Species) %>%
mutate(resid = model(Sepal.Length,Sepal.Width)) %>%
select(Sepal.Length,Sepal.Width,resid)
Который должен уступить:.
Species Sepal.Length Sepal.Width resid
<fctr> <dbl> <dbl> <dbl>
1 setosa 5.1 3.5 0.04428474
2 setosa 4.9 3.0 0.18952960
3 setosa 4.7 3.2 -0.14856834
4 setosa 4.6 3.1 -0.17951937
5 setosa 5.0 3.6 -0.12476423
6 setosa 5.4 3.9 0.06808885
Этот метод не должен быть вычислительно сильно отличается от того, с помощью augment()
(я имел использовать оба метода на наборах данных, содержащих несколько сотен миллионов наблюдений, и полагать, что не было существенной разницы в скорости по сравнению с использованием функции do()
).
Кроме того, обратите внимание, что опуская na.action = na.exclude
или с использованием m$residuals
вместо residuals(m)
, приведет к исключению строк, которые имеют Nas (упали до оценки) из выходного вектора невязок. Соответственно, соответствующий вектор не будет иметь достаточного количества length()
, чтобы быть объединенным с набором данных, и может появиться некоторое сообщение об ошибке.
(Я понимаю, что происходит, но я никогда бы не подумал об этом сам. Почему, например, мне нужна анонимная функция во втором 'do', но не в первом? –