18
votes

I have a data frame:

x <- data.frame(id = letters[1:3], val0 = 1:3, val1 = 4:6, val2 = 7:9)
#   id val0 val1 val2
# 1  a    1    4    7
# 2  b    2    5    8
# 3  c    3    6    9

Within each row, I want to calculate the corresponding proportions (ratio) for each value. E.g. for the value in column "val0", I want to calculate row-wise val0 / (val0 + val1 + val2).

Desired output:

  id     val0  val1   val2
1  a    0.083  0.33   0.583
2  b    0.133  0.33   0.533
3  c    0.167  0.33   0.5

Can anyone tell me what's the best way to do this? Here it's just three columns, but there can be alot of columns.

4

4 Answers

15
votes

following should do the trick

cbind(id = x[, 1], x[, -1]/rowSums(x[, -1]))
##   id       val0      val1      val2
## 1  a 0.08333333 0.3333333 0.5833333
## 2  b 0.13333333 0.3333333 0.5333333
## 3  c 0.16666667 0.3333333 0.5000000
14
votes

And another alternative (though this is mostly a pretty version of sweep)... prop.table:

> cbind(x[1], prop.table(as.matrix(x[-1]), margin = 1))
  id       val0      val1      val2
1  a 0.08333333 0.3333333 0.5833333
2  b 0.13333333 0.3333333 0.5333333
3  c 0.16666667 0.3333333 0.5000000

From the "description" section of the help file at ?prop.table:

This is really sweep(x, margin, margin.table(x, margin), "/") for newbies, except that if margin has length zero, then one gets x/sum(x).

So, you can see that underneath, this is really quite similar to @Jilber's solution.

And... it's nice for the R developers to be considerate of us newbies, isn't it? :)

9
votes

Another alternative using sweep

sweep(x[,-1], 1, rowSums(x[,-1]), FUN="/")
        val0      val1      val2
1 0.08333333 0.3333333 0.5833333
2 0.13333333 0.3333333 0.5333333
3 0.16666667 0.3333333 0.5000000
6
votes

The function adorn_percentages() from the janitor package does this:

library(janitor)
x %>% adorn_percentages()
 id       val0      val1      val2
  a 0.08333333 0.3333333 0.5833333
  b 0.13333333 0.3333333 0.5333333
  c 0.16666667 0.3333333 0.5000000

This is equivalent to x %>% adorn_percentages(denominator = "row"), though "row" is the default argument so is not needed in this case. An equivalent call is adorn_percentages(x) if you prefer it without the %>% pipe.

Disclaimer: I created the janitor package, but feel it's appropriate to post this; the function was built to perform exactly this task while making code clearer to read, and the package can be installed from CRAN.