Dividing a number in a column dfA with a number in a row dfB, based on the column name and the row name in R?

Viewed 20

I want to do something similar to index match match in Excel, but depending on the column name in dfA and the row name in dfB.

A subset example: dfA (my data) imported from excel and dfB is always the same (molar weight):

 dfA <- data.frame(Name=c("A", "B", "C", "D"),  #usually imported df from Excel
        Asp=c(2,4,6,8),
        Glu=c(1,2,3,4),
        Arg=c(5,6,7,8)) 

    > dfA
      Name Asp Glu Arg
    1 A    2   1   5
    2 B    4   2   6
    3 C    6   3   7
    4 D    8   4   8

X <- c("Arg","Asp","Glu")
Y <- c(174,133,147)
dfB <- data.frame(X,Y)

> dfB
    X   Y
1 Arg 174
2 Asp 133
3 Glu 147

I would like to divide the matching numbers from dfA with dfB, meaning R would "look up" and "take" the value from dfA and divide it with the value that "matches" in dfB. So for example take the value from sample named A under column "Arg" = 5, and divide it by the row "Arg" in dfB = 174 5 / 174 = 0.029 and make a new data frame called dfC. Looking like below:

#How R would calculate:
          Name Asp     Glu     Arg
        1 A    2/133   1/147   5/174
        2 B    4/133   2/147   6/174
        3 C    6/133   3/147   7/174
        4 D    8/133   4/147   8/174

>dfC
          Name Asp     Glu     Arg
        1 A    0.015   0.007   0.029
        2 B    0.030   0.014   0.034
        3 C    0.045   0.020   0.040
        4 D    0.060   0.027   0.046

I hope it makes sense :) I am really stuck and have no clear idea, how I can do this easily. I can only think of some weird work arounds, that take much longer than Excel. But I would like to standardize it, so I can use the R script everytime, I get data from the lab.

1 Answers

Here is a way. match the names of dfA, excluding the first with column dfB$X. Then apply a division to both dfA[-1] and dfB$Y. Finally, bind the result with the Name of dfA.

i <- match(names(dfA)[-1], dfB$X)
tmp <- mapply(\(x, y) x/y, dfA[-1], dfB$Y[i])
cbind(dfA[1], tmp)
#>   Name        Asp         Glu        Arg
#> 1    A 0.01503759 0.006802721 0.02873563
#> 2    B 0.03007519 0.013605442 0.03448276
#> 3    C 0.04511278 0.020408163 0.04022989
#> 4    D 0.06015038 0.027210884 0.04597701

Created on 2022-09-12 with reprex v2.0.2

Simpler, note the backticks:

tmp <- mapply(`/`, dfA[-1], dfB$Y[i])

Even simpler, do not create the temp matrix.

cbind(dfA[1], mapply(`/`, dfA[-1], dfB$Y[i]))
Related