1

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.

4 Answers4

3

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.

Community
  • 1
  • 1
Frank
  • 66,179
  • 8
  • 96
  • 180
2

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
Psidom
  • 209,562
  • 33
  • 339
  • 356
0

Using dplyr/tidyr:

library(dplyr)
library(tidyr)
df %>%
  gather(grade, value, -ID) %>%
  group_by(ID) %>%
  summarize(WtAvg = sum(as.numeric(grade) * value))
Edward R. Mazurek
  • 2,107
  • 16
  • 29
0

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) ] 
rafa.pereira
  • 13,251
  • 6
  • 71
  • 109