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
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'"
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.