如何在data.table中创建满足多列任一前缀匹配的标记变量
Fixing the "Any Column Starts With 'A'" Flag in data.table
Hey there! Let's sort out this flag variable you're trying to create. The problem with your current code is that you're calculating a single global maximum across all rows and columns in your .SD subset, which is why every row gets set to 1. Instead, we need to check per row if any of your target columns starts with "A".
First, Let's Recap Your Example Data
library(data.table) DT = as.data.table(matrix(c(LETTERS[seq(1,9)], rep("A",3)), nrow=3, ncol=4))
This gives us:
V1 V2 V3 V4 1: A D G A 2: B E H A 3: C F I A
Solution 1: Using rowSums (Simple & Vectorized)
This method leverages vectorized operations to efficiently check each row:
DT[, letterA := as.integer(rowSums(sapply(.SD, grepl, pattern = "^A")) > 0), .SDcols = c("V1", "V2")]
How it works:
sapply(.SD, grepl, "^A")generates a logical matrix where each column corresponds to one of your target columns (V1,V2), and each cell isTRUEif the value starts with "A".rowSums()counts how manyTRUEvalues exist per row.- Comparing to
> 0gives usTRUEif any column in the row meets the condition, andas.integer()converts that to 1/0.
Solution 2: Using Reduce (data.table-Friendly Logical OR)
This approach uses logical OR across columns per row, which is more explicit about the "any" condition:
DT[, letterA := as.integer(Reduce(`|`, lapply(.SD, grepl, pattern = "^A"))), .SDcols = c("V1", "V2")]
How it works:
lapply(.SD, grepl, "^A")creates a list of logical vectors (one for each target column).Reduce(|, ...)combines these vectors with a logical OR operation—so each row getsTRUEif any of the columns had a match.as.integer()again converts the logical result to 1/0.
Why Your Original Code Failed
Your line:
DT[, letterA:= max(apply(.SD,2,grepl,pattern= "^A" )), .SDcols=c("V1","V2")]
apply(.SD, 2, grepl, "^A")returns a matrix of logical values (rows = your data rows, columns =V1/V2).max()then takes the maximum of the entire matrix (which isTRUE/1 if any cell in those columns starts with "A"), resulting in a single value that gets assigned to all rows.
Result After Fixing
After running either solution, your DT will look like this:
V1 V2 V3 V4 letterA 1: A D G A 1 2: B E H A 0 3: C F I A 0
内容的提问来源于stack exchange,提问作者Noah Hammarlund
相关产品推荐
相关产品推荐

