我正在尝试编写一个函数,该函数需要一个data.table
,一个列列表和一个值列表,并选择行,以使每个列都被相应的值过滤。
因此,考虑以下data.table
:
> set.seed(1)
> dt = data.table(sample(1:5, 10, replace = TRUE),
sample(1:5, 10, replace = TRUE),
sample(1:5, 10, replace = TRUE))
> dt
V1 V2 V3
1: 1 5 5
2: 4 5 2
3: 1 2 2
4: 2 2 1
5: 5 1 4
6: 3 5 1
7: 2 5 4
8: 3 1 3
9: 3 1 2
10: 1 5 2
调用filterDT(dt, c(V1, V3), c(1, 2))
将选择V1 = 1
和V3 = 2
(上面的第3行和第10行)所在的行。
我最好的想法是使用.SD
和.SDcols
代表所需的列,然后在i
中进行比较(来自dt[i,j,by]
):
> filterDT <- function(dt, columns, values) {
dt[.SD == values, , .SDcols = columns]
}
> filterDT(dt, c("V1", "V3"), c(1, 2))
Empty data.table (0 rows and 3 cols): V1,V2,V3
不幸的是,即使仅按一列进行过滤,这也不起作用。
我注意到.SD
的所有示例都在j
中在线使用,这表明我可能做错了。
有什么建议吗?
答案 0 :(得分:4)
假设要filter
的“值”是与所选“列”相对应的值,我们可以与Map
和Reduce
和{{1}进行比较}
&
作为功能
dt[dt[ , Reduce(`&`, Map(`==`, .SD, values)) , .SDcols = columns]]
或者另一个选择是filterDT <- function(dt, columns, values) {
dt[dt[ , Reduce(`&`, Map(`==`, .SD, values)) , .SDcols = columns]]
}
filterDT(dt, c("V1", "V3"), c(1, 2))
# V1 V2 V3
#1: 1 4 2
setkey
答案 1 :(得分:4)
我认为您应该能够编写使用任意数量的列进行连接的函数:
public class FeedbackBody{
private final String email;
private final String feedback;
public FeedbackBody(String email, String feedback){
this.email = email;
this.feedback = feedback;
}
}
基本上,该函数从提供给#' Filter a data.table on an arbitrary number of columns
#'
#' @param dt data.table to filter
#' @param ... named columns to filter on and their values
filter_dt <- function(dt, ...) {
filter_criteria <- as.data.table(list(...))
dt[filter_criteria, on = names(filter_criteria), nomatch=0]
}
# A few examples:
filter_dt(dt, V1=1, V3=2)
filter_dt(dt, V1=2, V2=2, V3=5)
filter_dt(dt, V1=c(5,4,4), V3=c(1,2,5))
的参数构造一个新的data.table,每个参数成为新data.table ...
中的一列。然后将其提供给filter_criteria
的{{1}}参数,并将列名i
用作联接中的列。