Reputation:
Hi I'm new to R an have my first problem,
I have basically a data structure that looks pretty similar to:
ID <- c(1,2,3)
C <- c(0.4,0.4,0.2)
B <- c(0.4,0.3,0.2)
A <- c(0.2,0.3,0.6)
df <- data.frame(ID,A,B,C)
head(df)
ID A B C
1 1 0.2 0.4 0.4
2 2 0.3 0.3 0.4
3 3 0.6 0.2 0.2
where A,B,C correspond to grades A=1,B=2,C=3
I would like to compute the weighted average column for each row like:
ID 1 A*0.2 + B*0.4 + C*0.4
...
I tried:
as.numeric(as.character(names(df[,2:ncol(df)]))) * df[2:nrow(df),]
But that seems not right.
Upvotes: 1
Views: 78
Reputation: 66819
A standard way is: Put your thingamabob into an object
grades = c(A=1,B=2,C=3)
Then map-reduce
df$wt_grade = Reduce(`+`, Map(`*`, df[names(grades)], grades))
# or
df$wt_grade = Reduce(`+`, lapply(names(grades), function(x) df[[x]] * grades[x]))
The latter approach, borrowed from @eddi, is pretty fast.
Manually writing out the expression in terms of A, B and C (as in some other answers) will not extend well to additional grades or modifying the values associated with each grade.
Upvotes: 3
Reputation: 13807
A simple and fast solution using the data.table
approach
library(data.table)
setDT(df)[, w_avg := (A + B*2 + C*3)/(A+B+C) ]
Upvotes: 0
Reputation: 2177
Using dplyr/tidyr:
library(dplyr)
library(tidyr)
df %>%
gather(grade, value, -ID) %>%
group_by(ID) %>%
summarize(WtAvg = sum(as.numeric(grade) * value))
Upvotes: 0
Reputation: 214927
Something like this?
df$WtAvg = with(df, A + 2*B + 3*C)
df
ID A B C WtAvg
1 1 0.2 0.4 0.4 2.2
2 2 0.3 0.3 0.4 2.1
3 3 0.6 0.2 0.2 1.6
Upvotes: 2