对多个任意过滤条件使用 tidy eval

2023-12-07

我想用整齐的评价编写多个完全灵活的过滤条件。一个相关但不太复杂的问题已解决在这个 Stackoverflow 问题中。以下代码(改编自上述其他问题)正在运行。它将两个过滤条件应用于gapminder数据集,并返回过滤后的数据。

library(tidyverse)
library(gapminder)

my_filter <- function(df, cols, vals){    
  paste_filter <- function(x, y) quo(!!sym(x) %in% {{y}})
  fp <- pmap(list(cols, vals), paste_filter)
  filter(df, !!!fp)
}

cols <- list("country", "year")
vals = list(c("Albania", "France"), c(2002, 2007))
gapminder %>% my_filter(cols, vals) 

问题:到目前为止,该解决方案仅限于一种类型的过滤器运算符(%in%)。我想扩展这种方法来接受任意类型的运算符(==, %in%, >,...)。预期功能my_filter应该处理以下内容:

cols <- list("country", "year")
ops <- list("%in%", ">=")
vals = list(c("Albania", "France"), 2007))
gapminder %>% my_filter(cols, ops, vals)

我脑海中的用例是闪亮的应用程序。使用这样的功能,我们可以更轻松地让用户对数据集的变量设置任意过滤条件。


创建一个调用列表并将它们拼接到:

library(dplyr)
library(gapminder)

cols <- list("country", "year")
ops <- list("%in%", ">=")
vals <- list(c("Albania", "France"), 2007)

# Assumes LHS is the name of a variable and OP is
# the name of a function
op_call <- function(op, lhs, rhs) {
  call(op, sym(lhs), rhs)
}

my_filter <- function(data, cols, ops, vals) {
  exprs <- purrr::pmap(list(ops, cols, vals), op_call)
  data %>% dplyr::filter(!!!exprs)
}

gapminder %>% my_filter(cols, ops, vals)
#> # A tibble: 2 × 6
#>   country continent  year lifeExp      pop gdpPercap
#>   <fct>   <fct>     <int>   <dbl>    <int>     <dbl>
#> 1 Albania Europe     2007    76.4  3600523     5937.
#> 2 France  Europe     2007    80.7 61083916    30470.

在这里,我们不必担心范围问题,因为 (a) 假定列名在数据掩码中定义,(b) 值按值传递并内联到创建的调用中,(c) 函数假定为二元运算符,并且很少重新定义它们。

为了允许自定义用户功能,我们可以采用两种方法。首先,我们可以使用一个环境并手动创建配额new_quosure():

op_call <- function(op, lhs, rhs, env = caller_env()) {
  new_quosure(call(op, sym(lhs), rhs), env)
}

my_filter <- function(data, cols, ops, vals, env = caller_env()) {
  exprs <- purrr::pmap(list(ops, cols, vals), op_call, env)
  data %>% dplyr::filter(!!!exprs)
}

gapminder %>% my_filter(cols, ops, vals)

local({
  my_op <- `%in%`
  gapminder %>% my_filter(cols, list("my_op", ">="), vals)
})
#> # A tibble: 2 × 6
#>   country continent  year lifeExp      pop gdpPercap
#>   <fct>   <fct>     <int>   <dbl>    <int>     <dbl>
#> 1 Albania Europe     2007    76.4  3600523     5937.
#> 2 France  Europe     2007    80.7 61083916    30470.

另一种可能更简单的方法是允许调用包含内联函数。为此,请使用rlang::call2()代替base::call():

op_call <- function(op, lhs, rhs) {
  call2(op, sym(lhs), rhs)
}

my_filter <- function(data, cols, ops, vals) {
  exprs <- purrr::pmap(list(ops, cols, vals), op_call)
  data %>% dplyr::filter(!!!exprs)
}

local({
  my_op <- `%in%`
  gapminder %>% my_filter(cols, list(my_op, ">="), vals)
})
#> # A tibble: 2 × 6
#>   country continent  year lifeExp      pop gdpPercap
#>   <fct>   <fct>     <int>   <dbl>    <int>     <dbl>
#> 1 Albania Europe     2007    76.4  3600523     5937.
#> 2 France  Europe     2007    80.7 61083916    30470.

内联函数的缺点是,这将阻止优化和到其他 dplyr 后端的可移植性。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对多个任意过滤条件使用 tidy eval 的相关文章

  • 从 R 环境中删除对象

    我正在阅读 Hadley 的 Advanced R 在第 8 章中 他说我们可以使用以下方法从环境中删除对象 rm 但是 移除该物体后我仍然可以看到该物体 这是我的代码 e lt new env e a lt 1 e b lt 2 e a
  • 从 R 中的 HTTPS 连接逐行读取

    当创建连接时open r 它允许逐行读取 这对于批量处理大数据流非常有用 例如这个脚本 https gist github com jeroenooms d33a24958d99bb969ac0通过一次读取 100 行来解析相当大的 gzi
  • 将 VLMC 拟合到很长的序列

    我正在尝试将 VLMC 拟合到最长序列为 296 个状态的数据集 我这样做如下所示 Load libraries library PST library RCurl library TraMineR Load and transform d
  • 在另一个 Rmd 中运行选定的块

    我已经在源 Rmd 文件中运行了分析 并且希望仅使用few来自源的块 我已经看到了一些关于从源 Rmd 中提取所有块的答案来自另一个 Rmd 中的 Rmd 文件的源代码 https stackoverflow com questions 4
  • 将 sf voronoi 多边形裁剪到边界框时出错

    我正在尝试将 voronoi polygons 使用 sf package 创建 剪辑 到边界框 但它引发了我无法定义的错误 我对 R 的空间世界不太有经验 感谢所有帮助 样本数据 stations lt structure list ST
  • 根据另一列中的键累积一列中的值时出现问题

    我有一个看起来像这样的数据框 我需要使用 PROJ ID 列中的字符串创建一个新的值列 并形成 PROJ NAME 列中的值字符串 这里提供的解决方案 根据 r 中另一列的键累积一列中的值 https stackoverflow com q
  • 比较 R 中的两个字符向量

    我有两个 ID 字符向量 我想比较这两个字符向量 特别是我对以下数字感兴趣 A和B各有多少个ID 有多少个ID在A中但不在B中 有多少个ID在B但不在A 我还想画维恩图 以下是一些可以尝试的基础知识 gt A c Dog Cat Mouse
  • 如何将此“for”循环转换为向量解

    这个问题与 将嵌入其他文本的长州名称转换为两个字母的州缩写 https stackoverflow com questions 25582518 convert long state names embedded with other te
  • 表单提交时出现 rvest 错误

    我想从以下网页中抓取数据 https swgoh gg u zozo collection 180 emperor palpatine https swgoh gg u zozo collection 180 emperor palpati
  • R:将 JSON 时间格式转换为 POSIX

    我有一个 JSON 字符串 并将其放入数据框中 我能够做到这一点 但我在使用 apply 函数之一将所有时间字符串转换为 POSIX 格式时遇到问题 See here https stackoverflow com questions 90
  • 16 位以上整数的计算

    我有两个大整数 两者都超过 16 位 确切地说是 20 位 而且我知道由于双精度浮点运算 我在使用这些数字进行计算甚至将它们存储在变量中 独立于编程语言 时受到限制 不过 我想也许gmp图书馆应该处理它们 但不幸的是它没有 可以计算更大的整
  • R 中的 Websocket

    我设法在 R 中建立到 Mtgox websocket 的连接 规格如下 url https socketio mtgox com mtgox Currency USD https socketio mtgox com mtgox Curr
  • GGPLOT2:如何在 ggplot() 脚本中绘制特定选择

    这是一个名为的大型数据集的峰值P 其中有 10 个优惠 CS 有不同的商店 SHP 具有多个数值 数据集列出了按周排序的它们 WK 2 tm 52 它创建一个大文件 仅前 6 行出现峰值 WK MND CS SHP RevCY RevLY
  • 如何将 ggrough 图表另存为 .png

    说我正在使用R包裹ggrough https xvrdm github io ggrough https xvrdm github io ggrough 我有这个代码 取自该网页 library ggplot2 library ggroug
  • 非闪亮上下文中的反应式对象绑定

    实际问题 你怎样才能近似反应性环境 行为 http shiny rstudio com tutorial lesson6 建立者shiny http shiny rstudio com函数 或者甚至可能在一个函数中使用这些函数无光泽上下文以
  • R - tidyr - 变异并传播多列

    我在 R 中有以下数据框 my df test lt data frame V1 c 1 2 1 V2 c A B A V3 c S1 S1 S2 V4 c x x x V5 c y y y V6 c A B C V7 c D E F my
  • 捕获段错误、内存未映射错误

    我试图在 R 中找到 1347 x 209974 矩阵的列的相关性 每次我这样做 使用一个简单的命令cor matrix 我收到消息 caught segfault address 0xffffffffd058abf8 cause memo
  • 从“parallel”包中的非基础 R 包调用函数,而无需在函数中将它们库化

    假设我正在尝试运行以下代码 library gregmisc library parallel myfunction lt function x combinations 10 x 1 10 cl lt makeCluster getOpt
  • 使用 R 交互式更改 Plotly 图像中的轴刻度(线性/对数)

    Goal 创建交互式下拉菜单 按钮来更新 R 中 Plotly 图形的轴比例 Issue 有很多关于创建的文档buttons https plot ly r custom buttons and 对数图 https plot ly r lo
  • 如何一次导入多个 .csv 文件?

    假设我们有一个包含多个 data csv 文件的文件夹 每个文件包含相同数量的变量 但每个文件来自不同的时间 R 中有没有办法同时导入它们 而不必单独导入它们 我的问题是 我有大约 2000 个数据文件需要导入 并且必须使用以下代码单独导入

随机推荐