Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use names in one df to create same column copies of another dataframe

df <- structure(list(Cars = structure(3:1, .Label = c("Ford ", "Mazda", "Merc"), class = "factor"), Model = structure(c(2L, 1L, 3L), .Label = c("c", "e-class", "gt"), class = "factor"), Color = structure(1:3, .Label = c("Black ", "Blue", "Red"), class = "factor")), class = "data.frame", row.names = c(NA, -3L))
argument <- structure(list(NewVar = structure(3:2, .Label = c("", "SKU", "Vehicle"), class = "factor"), Input = structure(2:3, .Label = c("", "Cars", "Model"), class = "factor")), row.names = 1:2, class = "data.frame")
after <- structure(list(Cars = structure(3:1, .Label = c("Ford ", "Mazda", "Merc"), class = "factor"), Model = structure(c(2L, 1L, 3L), .Label = c("c", "e-class", "gt"), class = "factor"), Color = structure(1:3, .Label = c("Black ", "Blue", "Red"), class = "factor"), Vehicle = structure(3:1, .Label = c("Ford ", "Mazda", "Merc"), class = "factor"), SKU = structure(c(2L, 1L, 3L), .Label = c("c", "e-class", "gt"), class = "factor")), class = "data.frame", row.names = c(NA, -3L))
df
#>    Cars   Model  Color
#> 1  Merc e-class Black 
#> 2 Mazda       c   Blue
#> 3 Ford       gt    Red
argument
#>    NewVar Input
#> 1 Vehicle  Cars
#> 2     SKU Model
after
#>    Cars   Model  Color Vehicle     SKU
#> 1  Merc e-class Black     Merc e-class
#> 2 Mazda       c   Blue   Mazda       c
#> 3 Ford       gt    Red   Ford       gt

I am trying to for loop through the columns and create a copy based off the "argument" data.frame. This is what I tried but it's not really working. I have the df, the argument, and after dputs. Essentially, the argument has a column titled "new var", and "input". In argument, I have "Vehicle" in the "new var" and "input" in "Cars". This means within original df, copy "Cars" and title it "Vehicle".
List is dynamic so I am trying to keep it in for loops based off of length of the arguments, i.e. changing if I also want color to be copied as paint.

for (i in 1:length(argument$Input) ){
  df %>%   
  mutate( paste0(argument[i,1]) =  !!as.name(argument[i,2])
     }

Note, argument[i,1] refers to the input, so that "variable" is the new column name. In dplyr, this is affecting df, so i thought !!as.name would pull that variable that already exists i.e. "Cars" is already within before df.

like image 675
sammyramz Avatar asked Dec 31 '22 19:12

sammyramz


1 Answers

We can select the columns of interest with 'Input' column of 'argument', then use rename_at to change the column names. The 'argument' dataset columns are factor class, convert it to character while doing the changes.

library(dplyr)
df %>%
    mutate_at(vars(as.character(argument$Input)), list(new= ~ .)) %>% 
    rename_at(vars(matches('new')), ~ as.character(argument[[1]]))
#     Cars   Model  Color Vehicle     SKU
#1  Merc e-class Black     Merc e-class
#2 Mazda       c   Blue   Mazda       c
#3 Ford       gt    Red   Ford       gt

If we are using the OP's for loop with :=, make sure to evaluate (!!) the name strings on the lhs of :=

library(magrittr)
for(i in seq_len(nrow(argument))){
     df %<>%
         mutate(!! as.character(argument[[1]][i]) :=  
                 !! rlang::sym(as.character(argument[[2]][i])))
  }
like image 147
akrun Avatar answered Jan 08 '23 02:01

akrun