LDT
LDT

Reputation: 3088

Divide multiple columns with dplyr in R

My data frame looks like this, but I have hundreds of columns

t1 <- c(11,2,3,4)
t2 <- c(10,2,3,4)
total1 <- c(8,2,3,4)
total2 <- c(4,6,3,4)
test <- data.frame(t1,t2,total1,total2)
  t1 t2 total1 total2
1 11 10      8      4
2  2  2      2      6
3  3  3      3      3
4  4  4      4      4

I want to divide the t1/total2 and make a new column called freq1 and then t2/total2 and make a new column called freq2. I want to do this over hundreds of columns.

I want my data to look like this

    t1 t2 total1 total2 freq1 freq2
1   11 10    8      4    1.37 2.5
2   2  2     2      6    1.    0.33
3   3  3     3      3.   1.    1
4   4  4     4      4.   1.    1

I am working like this

mutate(freq1= t1/total1)

But this is problematic. I can not do it for all columns.

Upvotes: 0

Views: 317

Answers (4)

Ronak Shah
Ronak Shah

Reputation: 388982

Using dplyr you can gather two groups of columns together and divide them, give new names to columns and bind it to original data.

library(dplyr)

bind_cols(test, 
          (test %>% select(matches('t\\d+'))/
          test %>% select(matches('total\\d+'))) %>%
            rename_with(~paste0('freq', seq_along(.)))
          )

#  t1 t2 total1 total2 freq1     freq2
#1 11 10      8      4 1.375 2.5000000
#2  2  2      2      6 1.000 0.3333333
#3  3  3      3      3 1.000 1.0000000
#4  4  4      4      4 1.000 1.0000000

Upvotes: 1

akrun
akrun

Reputation: 887108

We can subset the datasets for 't' columns and the 'total' separately and divide them (assuming they are in the same order)

test[paste0('freq', 1:2)] <- test[1:2]/test[3:4]

Upvotes: 1

Taufi
Taufi

Reputation: 1577

A nice Base R solution that doesn't even need regex is as follows

df <- sapply(1:(ncol(test)/2), function(x) test[,x]/test[,x+(ncol(test)/2)])

The idea is that you have a number of columns that divides 2, so you can just use sapply() to divide a combination of columns.

Upvotes: 2

ThomasIsCoding
ThomasIsCoding

Reputation: 101335

Here is a base R option

cbind(
  test,
  lapply(
    split.default(
      test,
      paste0("freq", gsub("\\D", "", names(test)))
    ),
    Reduce,
    f = "/"
  )
)

which gives

  t1 t2 total1 total2 freq1     freq2
1 11 10      8      4 1.375 2.5000000
2  2  2      2      6 1.000 0.3333333
3  3  3      3      3 1.000 1.0000000
4  4  4      4      4 1.000 1.0000000

Upvotes: 1

Related Questions