简体   繁体   中英

How to do Dynamic dataframe indexing in R

I have two dataframes; sauce and rules. rules has a column called fieldname which consists of column names present in sauce. rules has a row called fieldvalue which consists of fileds pertaining to the column name in sauce. I want to be extract data from sauce based on fieldname and fieldvalue of rules.

I was trying to use for loops but they take too long and have not been able to get the correct result out of it.

> sauce <- data.frame(Type = c("ketchup","mustard","mayo","lite-mayo","ketchup"), Brand = c("Heinz","Publix","Kroger","Kroger","Kroger"))
> rules <- data.frame(fieldname = c("Type","Type","Brand"),
                        fieldvalue = c("ketchup","lite-mayo","Kroger"),
                          operator = c("and","or",""),
                            fielname2 = c("Brand","Brand",""),
                             fieldvalue2 = c("Heinz","Kroger",""))  

I am intending to index column names but using a different dataframe sauce[,c(rules$fieldname)]

I am ideally wanting to get data out of sauce based on rules dataframe.

for instance: fielname: Type and fieldvalue: ketchup (and being the operator) should result in ketchup Heinz as the output

  1. Create a vector of conditions using apply and sprintf from rules dataframe

     #Change and, or to &, | rules$operator_sym <- ifelse(rules$operator=="","",ifelse(rules$operator=="and",'&','|')) conds <- apply(rules, 1, function(x) if(length(x[x!=''])==6) sprintf("%s == '%s' %s %s == '%s'", x['fieldname'], x['fieldvalue'], x['operator_sym'], x['fielname2'], x['fieldvalue2']) else sprintf("%s == '%s'",x['fieldname'],x['fieldvalue'])) > conds [1] "Type == 'ketchup' & Brand == 'Heinz'" "Type == 'lite-mayo' | Brand == 'Kroger'" [3] "Brand == 'Kroger'" 
  2. Use map to loop through conds and filter sauce using the current condition. Use parse_exprs to transfer the condition from a string into R epression then evaluated using !!!

     library(dplyr) library(purrr) library(rlang) map(conds %>% set_names(), ~filter(sauce, !!!parse_exprs(.x))) $`Type == 'ketchup' & Brand == 'Heinz'` Type Brand 1 ketchup Heinz $`Type == 'lite-mayo' | Brand == 'Kroger'` Type Brand 1 mayo Kroger 2 lite-mayo Kroger 3 ketchup Kroger $`Brand == 'Kroger'` Type Brand 1 mayo Kroger 2 lite-mayo Kroger 3 ketchup Kroger 

Using map the output will be a list if you'd like the output as a dataframe you need map_dfr(conds %>% set_names(), ~filter(sauce, !!!parse_exprs(.x)), .id = "Condition")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM