【问题标题】:How to do Dynamic dataframe indexing in R如何在 R 中进行动态数据帧索引
【发布时间】:2019-10-17 12:17:08
【问题描述】:

我有两个数据框;酱汁和规则。规则有一个名为 fieldname 的列,其中包含酱汁中存在的列名。 rules 有一个名为 fieldvalue 的行,其中包含与酱汁中的列名相关的字段。我想根据规则的字段名和字段值从酱汁中提取数据。

我尝试使用 for 循环,但它们花费的时间太长,并且无法从中获得正确的结果。

> 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",""))  

我打算索引列名,但使用不同的数据框 sauce[,c(rules$fieldname)]

理想情况下,我希望根据规则数据框从酱汁中获取数据。

例如:字段名:类型和字段值:番茄酱(并且是操作员)应该导致番茄酱亨氏作为输出

【问题讨论】:

  • 如果您包含所需的输出会有所帮助。
  • 我已经更新了上面的数据框,因为我意识到它们没有画出足够好的画面。 sauce 有 200 条记录和 10 个变量。规则有 40 条记录,其中显示了变量。我试图得到的输出是酱汁的行 1. 其中 Type 是番茄酱,Brand 是 heinz,2. Type 是 lite-mayo 或 Brand 是 Kroger,3. Brand 是 Kroger。所以输出将是:从番茄酱亨氏酱汁中记录 1,在存在 lite-mayo 或克罗格的地方记录 3,4,5,在克罗格存在的地方记录 3,4,5。

标签: r dataframe indexing dynamic


【解决方案1】:
  1. 使用来自规则数据框的applysprintf 创建条件向量

    #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. 使用map 循环使用当前条件的condsfilter sauce。使用 parse_exprs 将条件从字符串转换为 R epression,然后使用 !!! 进行评估

    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
    

使用map,如果您希望将输出作为您需要的数据框map_dfr(conds %&gt;% set_names(), ~filter(sauce, !!!parse_exprs(.x)), .id = "Condition"),则输出将是一个列表

【讨论】:

  • 运行 map_dfr 时出现以下错误 parse_exprs(.x) 中的错误:找不到函数“parse_exprs”
  • @ZainA 使用library(rlang) 加载rlang 并确保您拥有rlang&gt;0.3.4
  • @ZainA 在我添加 operator_sym 列后,rules 将使用 6 列而不是 5 列,因此我检查非空列,即 !=' ' 是否相等到 6 与否。例如考虑 _rules length(rules[1,][rules[1,]!=''])==6length(rules[3,][rules[3,]!=''])==6 中的第 1 行和第 3 行
  • @a-suliman 如果规则将 fieldname3、fieldvalue3 和 operator1 作为第三个条件,conds 语句将如何变化
  • 我已经添加了以下内容:rules$operator1_sym &lt;- ifelse(rules$operator1=="","",ifelse(rules$operator1=="AND",'&amp;','|'))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-18
  • 2019-06-18
  • 2020-10-13
  • 2019-08-12
  • 1970-01-01
  • 2023-03-30
相关资源
最近更新 更多