Another option without using summarise
(the OP's code works in dplyr_0.4.1.9000
) to get the expected output would be extracting the coef
from lm
, convert it to list
, change the 'names' of list elements (setNames
) and convert back to data.frame
within the do
environment.
library(dplyr)
abc.fit <- abc_bySubject %>%
do(data.frame(setNames(as.list(coef(lm(value~delta, data=.))),
c('fvc_intercept','fvc_slope' ))))
abc.fit
# Subject fvc_intercept fvc_slope
#1 1 0.5319503 -0.03147698
#2 2 0.4478791 0.04293860
#3 3 0.4318059 -0.03276570
If we need to delete the 'Subject' column, we can ungroup()
and use select
to select columns other than 'Subject'
abc.fit %>%
ungroup() %>%
select(-Subject)
# fvc_intercept fvc_slope
#1 0.5319503 -0.03147698
#2 0.4478791 0.04293860
#3 0.4318059 -0.03276570
Another option would be data.table
. We convert the 'data.frame' to 'data.table' (setDT(abc)
), grouped by the 'Subject' column, we get the coefficients (coef
) of lm
, convert to list
(as.list
) and set the names of the columns (setnames
).
library(data.table)
res <- setnames(setDT(abc)[, as.list(coef(lm(value~delta))),
by =Subject],2:3, c('fvc_intercept', 'fvc_slope'))[]
res
# Subject fvc_intercept fvc_slope
#1: 1 0.5319503 -0.03147698
#2: 2 0.4478791 0.04293860
#3: 3 0.4318059 -0.03276570
We can subset the columns of interest from 'res'
res[,-1, with=FALSE]
# fvc_intercept fvc_slope
#1: 0.5319503 -0.03147698
#2: 0.4478791 0.04293860
#3: 0.4318059 -0.03276570
data
set.seed(24)
abc <- data.frame(Subject= rep(1:3,each=10), delta=rnorm(30), value=runif(30))
abc_bySubject <- group_by(abc, Subject)