A67John
A67John

Reputation: 103

Can I divide each column of dataframe using corresponding values from another dataframe in R?

I have two dataframes in R that look as follows:

#  A  B  C  D
#  4  12 1  6
#  3  5  3  8
#  6  1  9  4

where A,B,C,D are column names, and

#  id  value
#  A   10
#  B   15
#  C   12
#  D   20

where id and value are column names

I'm trying to write a code to divide all values in each column by a "value" from second dataframe. I've tried searching here, using some packages and writing my own loops by hand and nothing works. My dataframes have thousands of columns so I can't type it out by hand. Please help and thank you.

Upvotes: 3

Views: 553

Answers (3)

akrun
akrun

Reputation: 886998

Here is an option with deframe

library(tibble)
df1/deframe(df2)[col(df1)]
#   A          B          C   D
#1 0.4 0.80000000 0.08333333 0.3
#2 0.3 0.33333333 0.25000000 0.4
#3 0.6 0.06666667 0.75000000 0.2

Or using match in base R

df1/df2$value[match(df2$id, names(df1))][col(df1)]

data

df1 <- structure(list(A = c(4L, 3L, 6L), B = c(12L, 5L, 1L), C = c(1L, 
3L, 9L), D = c(6L, 8L, 4L)), class = "data.frame", row.names = c(NA, 
-3L))

df2 <- structure(list(id = c("A", "B", "C", "D"), value = c(10L, 15L, 
12L, 20L)), class = "data.frame", row.names = c(NA, -4L))

Upvotes: 1

markus
markus

Reputation: 26343

In baseR you could do

df1 / split(df2$value, names(df1))
#    A          B          C   D
#1 0.4 0.80000000 0.08333333 0.3
#2 0.3 0.33333333 0.25000000 0.4
#3 0.6 0.06666667 0.75000000 0.2

split(df2$value, names(df1)) returns a list that is sorted by names(df1):

split(df2$value, names(df1)
#$A
#[1] 10
#
#$B
#[1] 15
#
#$C
#[1] 12
#
#$D
#[1] 20

df1 is then divided columnwise by the values of that list.

data

df1 <- structure(list(A = c(4L, 3L, 6L), B = c(12L, 5L, 1L), C = c(1L, 
3L, 9L), D = c(6L, 8L, 4L)), class = "data.frame", row.names = c(NA, 
-3L))

df2 <- structure(list(id = c("A", "B", "C", "D"), value = c(10L, 15L, 
12L, 20L)), class = "data.frame", row.names = c(NA, -4L))

Upvotes: 3

tmfmnk
tmfmnk

Reputation: 39858

One dplyr solution could be:

df1 %>%
 rowwise() %>%
 mutate(across(everything())/df2$value)

      A      B      C     D
  <dbl>  <dbl>  <dbl> <dbl>
1   0.4 0.8    0.0833   0.3
2   0.3 0.333  0.25     0.4
3   0.6 0.0667 0.75     0.2

Upvotes: 2

Related Questions