Home > Software engineering >  Mutate several functions pairwise in a generalizable way in R
Mutate several functions pairwise in a generalizable way in R

Time:03-01

I have two vectors of names in my database (say one represent a component and second represent values) and I'm trying to develop a function that would create new columns based of the two vectors in a generalizable way I.E. something along the line of :

#vector components and values contain column names from the dataset

creaYK<-function(data,Input="A",Components=c("A", "B", "C"),Values=c("D", "E", "F")){
    
 for(i in 1:length(Values)){
      data<-data%>%mutate(new_i = sum(Values[i],Components[i]))
              
    }
}

my problem is that I need my arguments "vec1" and "vec2" to be modifiable in content and length and the calculation to be performed pairwise (each element of vec1 being summed to the corresponding in vec2). I have tried something with across() but it failed.

here is the desired output :

vec1<-c("A","B","C")
vec2<-c("D","E","F")

data<-tibble(A=1,B=2,C=3,D=4,E=5,F=6)

# what I want is a function returning :

# function(data,vec1,vec2)

tibble(A=1,B=2,C=3,D=4,E=5,F=6,ad=5,be=7,cf=9)

But the code above only creates one new column,and my attempts with mutate were also unsuccessful

Moreover, the name of indicators are not structured in the same way as the name of the value used

CodePudding user response:

If I understand you correctly, you might want

library(dplyr)

a <- c(2,5,6)
b <- c(4,9,6)
df <- as.data.frame(cbind(a,b))

tribble <- function(data,vec1,vec2){
  sum_v1v2 <- vec1 vec2
  a <- data %>% mutate(Sum_of_components = sum_v1v2)
}
b <- tribble(df,a,b)

Output:

  a b Sum_of_components
1 2 4                 6
2 5 9                14
3 6 6                12

CodePudding user response:

Your question is a little unclear, but here's an attempt. We can use Map to sum the values at the provided indices pairwise, and then use Map again to generate column names. Finally, cbind it all together:

library(tidyverse)

vec1<-c("A","B","C")
vec2<-c("D","E","F")

data<-tibble(A=1,B=2,C=3,D=4,E=5,F=6)

my_func <- function(data, vec1, vec2) {
  
  sums <- Map(\(lhs, rhs) {
    data[[lhs]]   data[[rhs]]
  }, vec1, vec2) %>% 
    as.data.frame()
  
  names <- Map(paste0, vec1, vec2) %>% 
    unlist() %>% 
    tolower()
  
  names(sums) <- names
  
  return(cbind(data, sums))
  
}

result <- my_func(data, vec1, vec2)

  A B C D E F ad be cf
  1 2 3 4 5 6  5  7  9

You could also do this in a loop, taking advantage of dplyr's dynamic column naming capabilities. But this is a very unorthodox approach:

for (i in seq_along(vec1)) {
  col1 <- vec1[i]
  col2 <- vec2[i]
  colname <- tolower(paste0(col1, col2))
  data <- data %>% 
    mutate({{colname}} := cur_data()[[col1]]   cur_data()[[col2]])
}
  • Related