寻求dplyr::filter_at的data.table等效实现方案
Great question! In data.table, you absolutely can replicate the clean, column-targeted filtering style of dplyr::filter_at()—and there are a couple of concise, idiomatic ways to do it. Let’s break them down with examples, using a sample data.table to make it concrete:
First, let’s set up some test data:
library(data.table) dt <- data.table( id = 1:5, test_1 = c("Passed", "Failed", "Passed", "Failed", "Failed"), test_2 = c("Failed", "Passed", "Failed", "Failed", "Failed"), extra_col = letters[1:5] )
Option 1: Using rowSums() with .SDcols (Most Concise)
This is the closest analog to filter_at() with any_vars(). We use .SDcols to specify which columns to check, then rowSums() to count how many of those columns have the value "Passed" in each row—we keep rows where this count is greater than 0.
Exact Column Match
If you want to target specific columns by name:
cols_to_check <- c("test_1", "test_2") dt[rowSums(.SD == "Passed") > 0, , .SDcols = cols_to_check]
Pattern-Based Column Match
Just like dplyr::starts_with() or contains(), you can use patterns() in .SDcols to match columns by a regex pattern (e.g., all columns starting with "test"):
dt[rowSums(.SD == "Passed") > 0, , .SDcols = patterns("^test_")]
Option 2: Using Reduce() for Flexible Logical ORs
If you need more flexibility (e.g., non-equality checks), you can use Reduce() to combine logical conditions across columns with the | (OR) operator. This works well for complex per-column logic:
cols_to_check <- c("test_1", "test_2") dt[Reduce(`|`, lapply(.SD, \(x) x == "Passed")), .SDcols = cols_to_check]
For context, this mirrors the dplyr code you’d write:
library(dplyr) dt %>% filter_at(vars(test_1, test_2), any_vars(. == "Passed"))
Both data.table approaches are idiomatic, performant, and keep the column-targeted filtering style you’re used to from filter_at(). The rowSums() method is generally faster and more concise for simple equality checks, while Reduce() gives you more control for custom conditions.
内容的提问来源于stack exchange,提问作者JdeMello

