r - 使用不同的过滤器参数和矢量化 fifelse() 在函数内过滤 data.table
问题描述
任务:我data.table
在用户定义的函数中有一个大数字(列 1:3 是子集所需的字符)来对数据执行分析。
在函数内进行下游分析之前,我想使用函数的参数传递值以过滤data.table
,或者如果没有为给定的列过滤器提供值,则使用所有行。
然而,困难出现了,因为并非所有的列过滤器都会一直使用。
目前,我的方法是使用单独的if
else
语句块进行过滤,以获取每列的 ID 列表,然后intersect
在使用它对data.table
. 该示例包括状态 3 列,但实际数据中有更多列,这使得这种方法笨拙且效率低下(尽管它有效)。
查询:是否有data.table
直接过滤的方法,因为不知道将使用哪些过滤列?ifelse()
或者,有没有办法用or来矢量化这个过程fifelse()
?
我什至会帮助将它嵌入到一个for
循环中,但为了让它工作,我需要动态创建变量名来存储每个 ID 列表。
我想保留使用data.table
和base
功能的解决方案。此外,函数的参数名称可以更改为与data.table
if 的列名称相同,这使得编码和可读性更容易。
我感谢提供的任何帮助。
数据:
# Install data.table package if not installed and load
if (!require("data.table")) {
install.packages("data.table")
library(data.table)
}
# Data (example)
head(DT, n=2)
#> ID info1 info2 name1 name2 name3 name4
#> <char> <char> <char> <dbl> <dbl> <dbl> <dbl>
#> 1: A100 StuffA StuffX 0.1460 NA -0.019 0.2102
#> 2: A101 StuffA StuffY 0.0987 -1.307 -0.174 NA
当前方法:
# Function (example)
myfunc <- function(ID_filter = "", info1_filter = "", info2_filter = "") {
# Get IDs to use as filter
if (ID_filter != "") {
ID_list <- DT[ID %in% ID_filter][["ID"]]
} else {
ID_list <- DT[["ID"]]
}
if (info1_filter != "") {
info1_list <- DT[info1 %in% info1_filter][["info1"]]
} else {
info1_list <- DT[["info1"]]
}
# Get overall filter list
filters <- Reduce(intersect, list(ID, info1, info2))
# Subset data.table
DT <- DT[ID %in% filters]
}
解决方案
该功能可以简化为
myfunc <- function(DT, ID_filter = "", info1_filter = "", info2_filter = "") {
lst1 <- Filter(function(x) all(x != ""),
dplyr::lst(ID_filter, info1_filter, info2_filter))
if(length(lst1) > 0 ) {
pat <- paste(sub("_filter", "", names(lst1)), collapse="|")
i1 <- DT[, Reduce(`&`, Map(`%in%`, .SD, lst1)), .SDcols = patterns(pat)]
DT[i1]
} else DT
}
-测试
setDT(DT)
myfunc(DT, ID_filter = "A100")
# ID info1 info2 name1 name2 name3 name4
#1: A100 StuffA StuffX 0.146 NA -0.019 0.2102
myfunc(DT, ID_filter = "A100", info1 = "StuffA")
# ID info1 info2 name1 name2 name3 name4
#1: A100 StuffA StuffX 0.146 NA -0.019 0.2102
myfunc(DT, ID_filter = "A100", info1 = "StuffA", info2 = "StuffX")
# ID info1 info2 name1 name2 name3 name4
#1: A100 StuffA StuffX 0.146 NA -0.019 0.2102
myfunc(DT, ID_filter = "A100", info1 = "StuffA", info2 = "StuffY")
#Empty data.table (0 rows and 7 cols): ID,info1,info2,name1,name2,name3...
myfunc(DT) # if all the parameters are "", return the full data
# ID info1 info2 name1 name2 name3 name4
#1: A100 StuffA StuffX 0.1460 NA -0.019 0.2102
#2: A101 StuffA StuffY 0.0987 -1.307 -0.174 NA
数据
DT <- structure(list(ID = c("A100", "A101"), info1 = c("StuffA", "StuffA"
), info2 = c("StuffX", "StuffY"), name1 = c(0.146, 0.0987), name2 = c(NA,
-1.307), name3 = c(-0.019, -0.174), name4 = c(0.2102, NA)),
class = "data.frame", row.names = c(NA,
-2L))
推荐阅读
- nuget - 使用面向多个框架的 NuGet 打包工具
- javascript - 如何扩展元素范围以允许稍后触发 onmouseout
- reactjs - 无法在反应测试库中使用模拟服务工作者
- testing - 如何使用 React-Admin 测试组件视图
? - python - 为什么这个白噪声频谱在频率 = 0 时有一个峰值?
- fb-hydra - 记录 Hydra 配置的好方法是什么?
- python - Python google colab OSError:SavedModel 文件不存在于:路径?
- android - 在适配器中显示数组
- python-3.x - 如何验证输入日期是否为 yyyy-mm-ddTHH:mm:ss.fffZ 格式?
- mysql - 如何同时从每个部门检索前 3 名最高薪和前 3 名最低薪