Home > Blockchain >  how to derive new variables from existing using a vector of values
how to derive new variables from existing using a vector of values

Time:01-09

here is the data what i have

temp <- tibble::tribble(
~x1, ~x2, ~x3, ~x4, ~x5,
1, 2, 3, 'AA', 'BB',
2, 3, 4, 'AB', 'CC',
3, 4, 5, 'AC', 'DD',
4, 5, 6, 'AD', 'EE',
5, 6, 7, 'AE', 'FF',
6, 7, 8, 'AF', 'GG'
) %>% dplyr::mutate(dplyr::across(x4,as.character), dplyr::across(x5,as.character))

I want to derive new variables 'px1', 'px2', 'px3' by multiplying with a vector temp_val with values c(1,2,3)

temp_val <- c(1,2,3)

I tried the below code

temp_val <- c(1,2,3)
nam1 <- c('px1','px2','px3')
temp5 <- temp %>% mutate(across(where(is.numeric), ~ . * temp_val, .names = '{nam1}'))

I get below data

enter image description here

my expectation, is to have vector values considered as columns and multiple variables with those columns

enter image description here

CodePudding user response:

We may create a named vector and then subset the elements of the temp_val based on the name derived from appending p to the column name looped (cur_column())

library(dplyr)
library(stringr)
names(temp_val) <- nam1
temp %>% 
  mutate(across(where(is.numeric), ~ 
  .x * temp_val[str_c("p", cur_column())], .names = "p{.col}"))

-output

# A tibble: 6 × 8
     x1    x2    x3 x4    x5      px1   px2   px3
  <dbl> <dbl> <dbl> <chr> <chr> <dbl> <dbl> <dbl>
1     1     2     3 AA    BB        1     4     9
2     2     3     4 AB    CC        2     6    12
3     3     4     5 AC    DD        3     8    15
4     4     5     6 AD    EE        4    10    18
5     5     6     7 AE    FF        5    12    21
6     6     7     8 AF    GG        6    14    24

Or another option if the names are in the same order, then use map2

library(purrr)
map2_dfc(temp %>% 
  select(where(is.numeric)), temp_val, `*`) %>% 
 setNames(nam1)%>% 
 bind_cols(temp, .)
# A tibble: 6 × 8
     x1    x2    x3 x4    x5      px1   px2   px3
  <dbl> <dbl> <dbl> <chr> <chr> <dbl> <dbl> <dbl>
1     1     2     3 AA    BB        1     4     9
2     2     3     4 AB    CC        2     6    12
3     3     4     5 AC    DD        3     8    15
4     4     5     6 AD    EE        4    10    18
5     5     6     7 AE    FF        5    12    21
6     6     7     8 AF    GG        6    14    24

CodePudding user response:

In addition to @akrun's answer, you could also use a row-wise calculation:

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
library(tidyr)
temp <- tibble::tribble(
  ~x1, ~x2, ~x3, ~x4, ~x5,
  1, 2, 3, 'AA', 'BB',
  2, 3, 4, 'AB', 'CC',
  3, 4, 5, 'AC', 'DD',
  4, 5, 6, 'AD', 'EE',
  5, 6, 7, 'AE', 'FF',
  6, 7, 8, 'AF', 'GG'
) %>% dplyr::mutate(dplyr::across(x4,as.character), dplyr::across(x5,as.character))


temp_val <- c(1,2,3)
nam1 <- c('px1','px2','px3')


temp %>% 
  rowwise() %>% 
  transmute(newvars = list(c_across(where(is.numeric))*temp_val)) %>% 
  unnest_wider(newvars) %>% 
  setNames(nam1) %>% 
  bind_cols(temp, .)
#> # A tibble: 6 × 8
#>      x1    x2    x3 x4    x5      px1   px2   px3
#>   <dbl> <dbl> <dbl> <chr> <chr> <dbl> <dbl> <dbl>
#> 1     1     2     3 AA    BB        1     4     9
#> 2     2     3     4 AB    CC        2     6    12
#> 3     3     4     5 AC    DD        3     8    15
#> 4     4     5     6 AD    EE        4    10    18
#> 5     5     6     7 AE    FF        5    12    21
#> 6     6     7     8 AF    GG        6    14    24

Created on 2023-01-08 by the reprex package (v2.0.1)

  •  Tags:  
  • r
  • Related