对多个任意过滤条件使用 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 的 for 循环中创建动态命名对象并分配动态值

    我正在尝试创建一套动态命名的新对象 例如 temp2015 使用 for 循环 并存储动态值 具体来说 其他对象的名称 例如 Y2015 和 for 循环中使用的值 例如 2015 在动态命名的新对象中 我不确定为什么下面的代码不起作用 Y
  • 闪亮的应用程序包:css 和所有 www/ 目录内容

    我正在尝试将 Shiny 应用程序转换为 R 包 但我在处理有关 www 目录以及 松散 文件的所有问题时遇到了问题 我闪亮的应用程序运行得很好 但是当我尝试 打包它 时 它不起作用 我闪亮的应用程序目录 my shiny app R ut
  • 从 data.frame 在 ggplot 图例中添加信息

    我想在图例中添加信息 哪个传感器具有该值 这是我的代码 z lt data frame a c sensor 1 sensor 2 sensor 3 sensor 4 sensor 5 sensor 6 sensor 7 sensor 8
  • 在r中的某个阈值处破坏 cumsum() 函数

    例如我有以下代码 cumsum 1 100 我想打破它 如果一个元素 i 1 大于3000 我怎样才能做到这一点 因此 而不是这个结果 1 1 3 6 10 15 21 28 36 45 55 66 78 91 105 120 136 15
  • R Shinydashboard 自定义 CSS 到 valueBox

    我一直在尝试将 valueBox 的颜色更改为自定义颜色 超出 validColors 中可用的颜色 但一直无法这样做 我知道有一种方法可以使用标签来包含自定义 CSS 但是我无法将它们放在正确的位置 ui lt dashboardPage
  • 从数据框中绘制多条平滑线

    我对 R 比较陌生 我正在尝试绘制从 csv 文件加载的数据框 数据由 6 列组成 如下所示 xval col1 col2 col3 col4 col5 第一列 xval 由一系列单调递增的正整数 例如 10 40 60 等 组成 其他列
  • 要在子集中显示的非数字条目的维恩图

    我有以下数据框 SET1 SET2 SET3 par1 par2 par1 par2 par3 par2 par3 par4 par5 我想制作一个维恩图 其中所有这些 parX 元素都显示在各自的子集中 即作为标签 而不仅仅是重叠元素的数
  • 如何根据 ggplot2 中的汇总数据创建堆积条形图

    我正在尝试使用 ggplot 2 创建堆积条形图 我的宽格式数据如下所示 每个单元格中的数字是响应的频率 activity yes no dontknow Social events 27 3 3 Academic skills works
  • 当将遗传算法与 lme4 一起使用时,glmulti 无限期运行

    我在 R 中使用 glmulti 进行模型平均 我的模型中有大约 10 个变量 使得详尽的筛选不切实际 因此我需要使用遗传算法 GA 调用 method g 我需要包含随机效应 因此我使用 glmulti 作为 lme4 的包装器 此处提供
  • 使用点阵个性化 R 上显示的 X 轴值

    我收集了大量包含日期 客户端及其 NFS 使用情况的数据 我正在使用lattice R包进行绘图 正如对超级用户的建议 https superuser com questions 523195 plot custom log data on
  • 平滑连续 2D 点

    UPDATE 感谢 user20650和 李哲源Zheyuan Li 这是我想出的解决方案 Example data set df 3600 observations points Create a vector of the cumula
  • 如何动态地将 sliderInput 添加到闪亮的应用程序中?

    使用闪亮 我上传一个 csv 文件 并根据列名称 我需要向 ui 添加滑块 sidebarPanel fileInput file1 Upload CSV File to Create a Model accept c text csv t
  • R - 基于列名称的子集

    我的数据框有超过 120 列 变量 我想根据列名称创建子集 例如 我想创建一个子集 其中列名称包含字符串 心情 这可能吗 我一般用 SubData lt myData grep whatIWant colnames myData 我很清楚
  • 计算 R 行中的非零条目数

    我有以下类型的数据 mode1 mode2 mode3 1 8 1 0 2 0 0 0 3 6 5 4 4 1 2 3 5 1 1 1 数据使用dput structure list mode1 c 8L 0L 6L 1L 1L mode2
  • 自定义轴缩放后 ggplot2 缺少标签

    我正在尝试使用我的 x 轴应用自定义缩放ggplot2 and scales trans new 但是 当我这样做时 一些轴标签丢失了 有人可以帮我弄清楚为什么吗 Setup library tidyverse the data ds lt
  • 无法将“gather”输出的列名称更改为默认名称以外的任何名称

    我正在尝试使用gather in the tidyr包 但我无法更改默认名称的输出列名称 例如 df data frame time 1 100 a 1 100 b 101 200 df long df gt gather foo bar
  • R 数据结构的运算效率

    我想知道是否有任何关于操作效率的文档R 特别是那些与数据操作相关的 例如 我认为向数据框添加列是有效的 因为我猜您只是向链接列表添加一个元素 我想添加行会更慢 因为向量保存在数组中C level你必须分配一个新的长度数组n 1并将所有元素复
  • 在 RGL 中将立方体绘制到 3D 散点图中

    我正在尝试向 3D 散点图添加较小的立方体 网格 具有指定边长 我希望立方体位于原点 我该怎么做呢 我已经玩过cube3d 但我似乎无法将立方体正确定位 也无法使其成为网格 因此我可以看到它包含的数据点 这是我所拥有的 library rg
  • 是否有weighted.median()函数?

    我正在寻找类似形式的东西weighted mean 我通过搜索找到了一些解决方案 这些解决方案写出了整个函数 但希望有一些更用户友好的解决方案 以下软件包都有计算加权中位数的函数 aroma light isotone limma cwhm
  • 如何在R中分离两个图?

    每当我运行这段代码时 第一个图就会简单地覆盖前一个图 R中有没有办法分开得到两个图 plot pc title main abc xlab xx ylab yy plot pcs title main sdf xlab sdf ylab x

随机推荐