mindlessgreen
mindlessgreen

Reputation: 12112

R Aggregate without summarising

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

Answers (3)

Sumedh
Sumedh

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

akrun
akrun

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

RHertel
RHertel

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

Related Questions