Home > Mobile >  Multiply a column in a list element by a vector using map() in R to create new columns
Multiply a column in a list element by a vector using map() in R to create new columns

Time:10-07

I have a list of multiple elements (13 elements each of different dimensions but the column names are the same), e.g.:

tbl1 <- tibble(Code = c(1,2,3,4),
               Column1 = c(10,11,12,13),
               Column2 = c(14,15,16,17))

tbl2 <- tibble(Code = c(5,6,7,8),
               Column1 = c(14,15,16,17),
               Column2 = c(18,19,20,21))


my_list <- list(Element1 = tbl1, Element2 = tbl2)

vector <- c(0.5, 0.6, 0.7, 0.8)

I want to multiply Column2 of each list element by each vector element and bind the resulting column to the dataframe like this:

my_list %>%
  map(.f = function(x) x %>% 
        mutate(!!paste0("Column_", vector[1]) := pmap_dbl(list(Column2, vector[1]), prod),
               !!paste0("Column_", vector[2]) := pmap_dbl(list(Column2, vector[2]), prod),
               !!paste0("Column_", vector[3]) := pmap_dbl(list(Column2, vector[3]), prod),
               !!paste0("Column_", vector[4]) := pmap_dbl(list(Column2, vector[4]), prod)))

$Element1
# A tibble: 4 x 7
   Code Column1 Column2 Column_0.5 Column_0.6 Column_0.7 Column_0.8
  <dbl>   <dbl>   <dbl>      <dbl>      <dbl>      <dbl>      <dbl>
1     1      10      14        7          8.4        9.8       11.2
2     2      11      15        7.5        9         10.5       12  
3     3      12      16        8          9.6       11.2       12.8
4     4      13      17        8.5       10.2       11.9       13.6

$Element2
# A tibble: 4 x 7
   Code Column1 Column2 Column_0.5 Column_0.6 Column_0.7 Column_0.8
  <dbl>   <dbl>   <dbl>      <dbl>      <dbl>      <dbl>      <dbl>
1     5      14      18        9         10.8       12.6       14.4
2     6      15      19        9.5       11.4       13.3       15.2
3     7      16      20       10         12         14         16  
4     8      17      21       10.5       12.6       14.7       16.8

but I cannot figure out how to iterate it through the vector... How do I change mutate(!!paste0("Column_", vector[x]) := pmap_dbl(list(Column2, vector[x]), prod) to a map() so it can be as generic as possible and can be used with a vector of any length?

Look forward to your thoughts!

Thank you

CodePudding user response:

Here's one strategy. Basically you use map_dfc to turn the vector into a bunch of columns.

map(my_list, function(x) {
   bind_cols(x, map_dfc(set_names(vector, paste0("Column_", vector)), ~x$Column2*.x))
})

Since we have a nested map, I used an explicit function for the outer function that receives each data.frame. This will help differentiation between x (the data.frame) and .x (the value of vector). We use set_names so that map_dfc will use those as the names of the new columns it creates. The actual multiplication doesn't need a map because multiplication is vectorized in R.

CodePudding user response:

Base R attempt -

cols <- paste0('Column_', vector)

lapply(my_list, function(x) {
  x[cols] <- lapply(vector, `*`, x$Column2)
  x
})

#$Element1
# A tibble: 4 x 7
#   Code Column1 Column2 Column_0.5 Column_0.6 Column_0.7 Column_0.8
#  <dbl>   <dbl>   <dbl>      <dbl>      <dbl>      <dbl>      <dbl>
#1     1      10      14        7          8.4        9.8       11.2
#2     2      11      15        7.5        9         10.5       12  
#3     3      12      16        8          9.6       11.2       12.8
#4     4      13      17        8.5       10.2       11.9       13.6

#$Element2
# A tibble: 4 x 7
#   Code Column1 Column2 Column_0.5 Column_0.6 Column_0.7 Column_0.8
#  <dbl>   <dbl>   <dbl>      <dbl>      <dbl>      <dbl>      <dbl>
#1     5      14      18        9         10.8       12.6       14.4
#2     6      15      19        9.5       11.4       13.3       15.2
#3     7      16      20       10         12         14         16  
#4     8      17      21       10.5       12.6       14.7       16.8
  • Related