r - 在 R 中模拟动态范围以按任意函数进行过滤
问题描述
我在一个目录中有许多文件,我想根据它们的内容是否满足某个条件,将它们分布在两个新创建的子目录之间。而且,我需要对多个目录执行这个操作,而且每次的条件可能都不一样。
我想我会这样做的方法是创建一个高阶函数,它读取文件,从每个文件中提取感兴趣的属性,然后应用条件(作为函数形式的参数提供)元素-明智的值的结果向量:
filter.by.property <- function(where, funct) {
setwd(where)
paths <- list.files(".", pattern = ".file")
Robjects <- Map(read.file, paths)
values <- sapply(Robjects, function(x) property_of_interest(x))
passes <- Filter(funct, paths)
dir.create("dir1")
dir.create("dir2")
file.copy(passes, paste("./dir1/", 1:length(passes), ".file", sep = ""))
file.copy(paths[!paths %in% passes], paste("./dir2/", (length(passes) + 1):length(paths), ".file", sep = ""))
}
问题是我希望条件指定函数(在funct
参数中提供)能够访问values
向量。例如:
ten.biggest <- function(path) {
Robject <- read.file(path)
property_of_interest(x) %in% tail(sort(values), 10)
}
filter.by.property(<place>, ten.biggest)
由于 R 是词法范围的,它会values
在ten.biggest
定义的环境(全局环境)中查找,而不是在调用它的环境(即 inside filter.by.property
)中查找。values
我可以通过对inside使用全局赋值来解决这个问题filter.by.property
,但除非绝对必要,否则我不希望这样做。我也可以values
作为另一个参数提供给ten.biggest
,但是该函数将不再是一元的,而且我不确定它如何(甚至是否)仍然可以在Filter
.
我尝试的一种解决方案是重写ten.biggest
如下
ten.biggest <- function(path) {
Robject <- read.file(path)
property_of_interest(x) %in% tail(sort(eval.parent(parse(text = values))), 10)
}
但这没有用。
有什么方法可以模拟 R 中的动态范围来完成这项工作?通过阅读相关的 StackExchange 问题,似乎该body
功能可能会有所帮助,但我不知道如何将其应用于我的问题。
解决方案
我找到了一个不依赖于切换环境的解决方案。我允许使用两个参数,并在内部ten.biggest
定义了一个辅助函数 ,通过设置其中一个参数将二进制函数转换为一元函数。然后可以通过后者的参数将二进制函数传递给,将 的参数设置为by ,然后可以在内部使用生成的一元函数:outer_fxn
filter.by.property
ten.biggest
filter.by.property
funct
vals
ten.biggest
values
outer_fxn
Filter
ten.biggest <- function(path, vals) {
Robject <- read.file(path)
property_of_interest(x) %in% tail(sort(vals), 10)
}
filter.by.property <- function(where, funct) {
setwd(where)
paths <- list.files(".", pattern = ".file")
Robjects <- Map(read.file, paths)
values <- sapply(Robjects, function(x) property_of_interest(x))
outer_fxn <- function(x) { funct(x, values) }
passes <- Filter(outer_fxn, paths)
dir.create("dir1")
dir.create("dir2")
file.copy(passes, paste("./dir1/", 1:length(passes), ".file", sep = ""))
file.copy(paths[!paths %in% passes], paste("./dir2/", (length(passes) + 1):length(paths), ".file", sep = ""))
}
推荐阅读
- r - R 4.1.0 的软件包安装问题
- javascript - 从 JavaScript 向 Sinatra 端点发送 POST 请求
- c# - Xmarin 中的 C# 选择器
- java - 如何使用 Hibernate 和 Windows 身份验证连接到 SQL Server 2017?
- javascript - 无法深度克隆
- python - Apache Beam Python gscio 上传方法已实现@retry.no_retries 导致数据丢失?
- python-3.x - 在 sqlalchemy 过滤器中使用 and_ 不起作用
- sql - 几何类型的替代 First() 函数
- r - 使用 DoParallel R 将 FOR 循环更改为 FOR EACH 循环
- python - 在 Python 中的列中裁剪字符串