Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dividing selected columns by vector in dplyr

Tags:

r

dplyr

This has to be simple in base R, but it is driving me crazy with dplyr (which overall has made my life much better!). Suppose you have the following tibbles

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union



df1 <- tibble(x=seq(5)*19, a1=seq(5)*1, a2=seq(5)*2, a3=seq(5)*4)

df1
#> # A tibble: 5 x 4
#>       x    a1    a2    a3
#>   <dbl> <dbl> <dbl> <dbl>
#> 1    19     1     2     4
#> 2    38     2     4     8
#> 3    57     3     6    12
#> 4    76     4     8    16
#> 5    95     5    10    20


df2 <- tibble(b1=3, b2=0.5, b3=10)

df2
#> # A tibble: 1 x 3
#>      b1    b2    b3
#>   <dbl> <dbl> <dbl>
#> 1     3   0.5    10

Created on 2020-06-11 by the reprex package (v0.3.0)

Then I simply want to replace in df1 a1 with a1/b1, a2 with a2/b2 and so on. This has to be general enough to handle the case when I have many columns. Any suggestion is appreciated.

like image 900
larry77 Avatar asked Jun 11 '20 12:06

larry77


2 Answers

You can use Map

df1[-1] <- Map(`/`, df1[-1], df2)

# A tibble: 5 x 4
#      x    a1    a2    a3
#  <dbl> <dbl> <dbl> <dbl>
#1    19 0.333     4   0.4
#2    38 0.667     8   0.8
#3    57 1        12   1.2
#4    76 1.33     16   1.6
#5    95 1.67     20   2  

Or if you want a tidyverse solution you can use map2 in purrr :

df1[-1] <- purrr::map2(df1[-1], df2, `/`)
like image 81
Ronak Shah Avatar answered Sep 22 '22 04:09

Ronak Shah


You can use rowwise() with c_across()

df1 %>%
  rowwise() %>% 
  mutate(c_across(a1:a3) / df2, .keep = "unused") %>%
  ungroup()

# # A tibble: 5 x 4
#       x    b1    b2    b3
#   <dbl> <dbl> <dbl> <dbl>
# 1    19 0.333     4   0.4
# 2    38 0.667     8   0.8
# 3    57 1        12   1.2
# 4    76 1.33     16   1.6
# 5    95 1.67     20   2  

Another base R option

df1[-1] <- t(t(df1[-1]) / unlist(df2))
df1

# # A tibble: 5 x 4
#       x    a1    a2    a3
#   <dbl> <dbl> <dbl> <dbl>
# 1    19 0.333     4   0.4
# 2    38 0.667     8   0.8
# 3    57 1        12   1.2
# 4    76 1.33     16   1.6
# 5    95 1.67     20   2  
like image 30
Darren Tsai Avatar answered Sep 23 '22 04:09

Darren Tsai