Reputation:
I have a function (la) that I would like to apply to some data
la<-function(x) {
res<-mean(x)^2
return(c(res,res^2))
}
a<-c(1,3,5,6)
b<-c(5,8,9,10)
df<-data.frame(a,b)
colnames(df)<-c('tata','toto')
all<-stack(df)
> aggregate(all$values, by=list(all$ind), FUN=la)
Group.1 x.1 x.2
1 tata 14.0625 197.7539
2 toto 64.0000 4096.0000
and I get the values for a :
> aggregate(all$values, by=list(all$ind), FUN=la)[,2][,1]
[1] 14.0625 64.0000
My question: Is it possible to create a new column to the data.frame 'all', where the third column will be the first column multiplied by 14.0625 and 64.0000 (depending on the factor) ?
Many thanks
Upvotes: 0
Views: 51
Reputation: 28675
Using your custom function and aggregate code you could do
la<-function(x) {
res<-mean(x)^2
return(c(res,res^2))
}
agg <- aggregate(all$values, by=list(all$ind), FUN=la)
mult <- setNames(agg[,2][,1], agg[[1]])
all$all <- all$values*mult[all$ind]
all
# values ind all
# 1 1 tata 14.0625
# 2 3 tata 42.1875
# 3 5 tata 70.3125
# 4 6 tata 84.3750
# 5 5 toto 320.0000
# 6 8 toto 512.0000
# 7 9 toto 576.0000
# 8 10 toto 640.000
However, if this is all you're trying to accomplish you don't need the custom function and aggregate, and can use the code below instead.
library(dplyr)
all %>%
group_by(ind) %>%
mutate(all = values*mean(values)^2)
# # A tibble: 8 x 3
# # Groups: ind [2]
# values ind all
# <dbl> <fct> <dbl>
# 1 1 tata 14.1
# 2 3 tata 42.2
# 3 5 tata 70.3
# 4 6 tata 84.4
# 5 5 toto 320
# 6 8 toto 512
# 7 9 toto 576
# 8 10 toto 640
Or with data.table
library(data.table)
setDT(all)
all[, all := values*mean(values)^2, by = ind]
all
# values ind all
# 1: 1 tata 14.0625
# 2: 3 tata 42.1875
# 3: 5 tata 70.3125
# 4: 6 tata 84.3750
# 5: 5 toto 320.0000
# 6: 8 toto 512.0000
# 7: 9 toto 576.0000
# 8: 10 toto 640.0000
Upvotes: 2
Reputation: 72673
You may use ave
.
all$newcol1 <- with(all, ave(values, ind, FUN=function(x) x * la(x)))
all
# values ind newcol
# 1 1 tata 14.0625
# 2 3 tata 42.1875
# 3 5 tata 70.3125
# 4 6 tata 84.3750
# 5 5 toto 320.0000
# 6 8 toto 512.0000
# 7 9 toto 576.0000
# 8 10 toto 640.0000
Upvotes: 2
Reputation: 4367
You already have an answer, but another (more cumbersome) solution:
la<-function(x) {
res<-mean(x)^2
return(c(res,res^2))
}
a<-c(1,3,5,6)
b<-c(5,8,9,10)
df<-data.frame(a,b)
colnames(df)<-c('tata','toto')
all<-stack(df)
all_2 <- merge(
all,
aggregate(all$values, by=list(all$ind), FUN=la),
by.x = 'ind',
by.y = 'Group.1')
all_2$newvalue <- all_2$values * all_2$x[,1]
all_2 <- all_2[,c(1,2,4)]
# > all_2
# ind values newvalue
# 1 tata 1 14.0625
# 2 tata 3 42.1875
# 3 tata 5 70.3125
# 4 tata 6 84.3750
# 5 toto 5 320.0000
# 6 toto 8 512.0000
# 7 toto 9 576.0000
# 8 toto 10 640.0000
Upvotes: 1