Search code examples
rweighted-average

Weighted means for all columns in R data.frame


I have a 32x43 data.frame called "allg2", and I recreated a small portion of it here as 5x5 for simplicity:

gneiss mylonite syenite sedimentary Catg
0      3        4       0           -105.7
2      90       1       0           -99.7
15     51       0       0           -95.25
6      0        0       0           -90.5
0      3        9       0           -85.45

As requested, a sample calculation: The 'gneiss' column would be wm=(0/21*-105.7)+(2/21*-99.7)+(15/21*-95.25)+(6/21*-90.5)+(0/21*-85.45)

I would like a weighted mean for each column (with the values of interest in Catg, and each column as the weights for that column), but each solution to this that I can find relies on coding in all of the column names. Is it possible to do this without such a list? Note: I just realized that I have been flipping the weights and values to weigh the entire time. My attempts:

wm=allg2[,lapply(.SD,weighted.mean,w=Catg),by=list(allg2[1,])]
Error: unused argument (by = list(allg2[1, ]))

I found this idea from this thread, and tried to adapt it to my situation. Is it not selecting the column names because they're not a true row? I don't really know what this is doing, and I tried temoving the by= part, which gives the error

 Error in lapply(.SD, weighted.mean, w = Catg) : object '.SD' not found

Another attempt was based on this thread. "Catg" is in the 43rd column, so I tried organizing the line as such:

wm=apply(allg2, 2, function(x) weighted.mean(x[,43], x[,1:42]))
Error in x[, 43] : incorrect number of dimensions

I really don't understand this error, because my column of weights should be in [,43].

I have also tried:

mallg=data.matrix(allg2)
wm=colWeightedMeans(mallg,allg2$Catg)
Error in colWeightedMeans.matrix(mallg, allg2$Catg) : Argument 'w' has negative weights.

I'm really at a loss here. Am I making some small error or am I going about this the completely wrong way?


Solution

  • Assuming that your weights are in the last column:

    ll <- lapply(df[ , -ncol(df)], weighted.mean,  w = df$Catg)
    ll
    # $gneiss
    # [1] 4.555497
    # 
    # $mylonite
    # [1] 30.22283
    # 
    # $syenite
    # [1] 2.709924
    # 
    # $sedimentary
    # [1] 0
    

    Edit: following your comment, you now need to do:

    lapply(df[ , -ncol(df)], weighted.mean, x = df$Catg)