generate new columns by dplyr mutate or purrr map

I have dataframe

set.seed(2021)
data.frame(map(0:5, rnorm, n=10))%>%
  setNames(c('art_1','art_2','vl_1','vl_2','dg_1','dg_2'))
         art_1       art_2      vl_1     vl_2     dg_1     dg_2
1  -0.12245998 -0.08220485 1.0575567 1.036175 4.116389 4.499709
2   0.55245663  0.72717482 1.8143150 1.552056 5.760214 2.744131
3   0.34864950  1.18199540 0.8988754 4.019443 3.654884 5.043741
4   0.35963224  2.50854179 3.2081153 1.578583 6.120000 4.631182
5   0.89805369  2.60447011 0.3750615 2.395468 3.965623 4.039778
6  -1.92256952 -0.84147561 2.1053783 1.416526 3.207846 5.103766
7   0.26174436  2.62331021 0.5445567 1.714068 5.475515 5.427289
8   0.91556637  1.13138902 1.6459839 1.545315 3.274443 4.829518
9   0.01377194  2.48112247 1.9063000 2.912929 4.312379 3.450860
10  1.72996316  2.51331829 3.1006686 3.504736 4.691964 3.494400

I need generate new columns 'art','vl','dg' art = art_1 / art_2 vl = vl_1 / vl_2 dg = dg_1 / dg_2

do not manually

please help me

Upvotes: 1

Views: 425

Answers (2)

AnilGoyal
AnilGoyal

Reputation: 26218

This will do. Stepwise explanation-

  • store different variable names without prefix/suffix in a vector say vars
  • use mutate across
  • to pass variable names say with suffix _1 use !! operator along with glue::glue()
  • now . (.x) in lambda function will act as these variables
  • For changing suffixes use str_replace alongwith get()
  • .names argument follow glue specifications. so use just '{vars}' here.
  • You're done.
vars <- c('art','vl','dg')

df %>% mutate(across(!!glue::glue('{vars}_1'), 
                     ~ . / get(str_replace(cur_column(), "1", "2")), 
                     .names = '{vars}'))

         art_1       art_2      vl_1     vl_2     dg_1     dg_2         art        vl        dg
1  -0.12245998 -0.08220485 1.0575567 1.036175 4.116389 4.499709 1.489692871 1.0206354 0.9148122
2   0.55245663  0.72717482 1.8143150 1.552056 5.760214 2.744131 0.759730141 1.1689755 2.0991033
3   0.34864950  1.18199540 0.8988754 4.019443 3.654884 5.043741 0.294966886 0.2236318 0.7246374
4   0.35963224  2.50854179 3.2081153 1.578583 6.120000 4.631182 0.143363067 2.0322754 1.3214770
5   0.89805369  2.60447011 0.3750615 2.395468 3.965623 4.039778 0.344812439 0.1565713 0.9816438
6  -1.92256952 -0.84147561 2.1053783 1.416526 3.207846 5.103766 2.284759642 1.4862969 0.6285252
7   0.26174436  2.62331021 0.5445567 1.714068 5.475515 5.427289 0.099776368 0.3176985 1.0088859
8   0.91556637  1.13138902 1.6459839 1.545315 3.274443 4.829518 0.809240992 1.0651445 0.6780061
9   0.01377194  2.48112247 1.9063000 2.912929 4.312379 3.450860 0.005550689 0.6544272 1.2496535
10  1.72996316  2.51331829 3.1006686 3.504736 4.691964 3.494400 0.688318376 0.8847081 1.3427095

Upvotes: 1

MKR
MKR

Reputation: 1700

Very simply with dplyr. You can use mutate for this. I suggest you do a quick dplyr tutorial.

library(dplyr)
df <- data.frame(map(0:5, rnorm, n=10))%>% setNames(c('art_1','art_2','vl_1','vl_2','dg_1','dg_2'))

df %>% 
  mutate(art = art_1 / art_2,
         vl = vl_1 / vl_2,
         dg = dg_1 / dg_2)

Upvotes: 1

Related Questions