Reputation: 12112
I have a data frame like below.
dat <- data.frame(k=c("A","A","B","B","B"),a=c(2,3,1,3,4),b=c(5,8,2,1,2))
> dat
k a b
1 A 2 5
2 A 3 8
3 B 1 2
4 B 3 1
5 B 4 2
I would like to aggregate a and b over k while maintaining the original data structure. The two approaches below summarise the results.
aggregate(.~k,data=dat,mean)
k a b
1 A 2.500000 6.500000
2 B 2.666667 1.666667
plyr::ddply(dat,.(k),colwise(mean))
k a b
1 A 2.500000 6.500000
2 B 2.666667 1.666667
But I am looking for a result like this:
k a b
1 A 2.50 6.50
2 A 2.50 6.50
3 B 2.66 1.66
4 B 2.66 1.66
5 B 2.66 1.66
Any simple solution for this? Thanks.
Upvotes: 1
Views: 275
Reputation: 4965
Using data.table
:
library(data.table)
setDT(dat)[ , c("a", "b") := lapply(.SD, mean), by = k]
dat
k a b
1: A 2.500000 6.500000
2: A 2.500000 6.500000
3: B 2.666667 1.666667
4: B 2.666667 1.666667
5: B 2.666667 1.666667
Upvotes: 1
Reputation: 887251
We can use mutate_each
from dplyr
library(dplyr)
dat %>%
group_by(k) %>%
mutate_each(funs(mean))
# k a b
# <fctr> <dbl> <dbl>
#1 A 2.500000 6.500000
#2 A 2.500000 6.500000
#3 B 2.666667 1.666667
#4 B 2.666667 1.666667
#5 B 2.666667 1.666667
Upvotes: 1
Reputation: 23798
You can use ave()
:
dat[-1] <- sapply(dat[-1],ave,dat$k)
#> dat
# k a b
#1 A 2.500000 6.500000
#2 A 2.500000 6.500000
#3 B 2.666667 1.666667
#4 B 2.666667 1.666667
#5 B 2.666667 1.666667
Upvotes: 2