data.table R 中带列表的赋值运算符

data.table assignment operator with lists in R

我有一个包含 name 列的 data.table,我正在尝试从此名称中提取正则表达式。在这种情况下,最明显的方法是使用 := 运算符,因为我将这个提取的字符串指定为数据的实际名称。在这样做的过程中,我发现这实际上并没有以我期望的方式应用该功能。我不确定这是否是故意的,我想知道它这样做是否有原因,或者它是否是一个错误。

library(data.table)
dt <- data.table(name = c('foo123', 'bar234'))

在简单字符向量中搜索所需表达式的行为符合预期:

name <- dt[1, name]
pattern <- '(.*?)\d+'
regmatches(name, regexec(pattern, name))
[[1]]
[1] "foo123" "foo"  

我可以轻松地对其进行子集化以获得我想要的

regmatches(name, regexec(pattern, name))[[1]][2]
[1] "foo"

但是,当我尝试将其应用于整个 data.table:

时,我 运行 遇到了问题
dt[, name_final := regmatches(name, regexec(pattern, name))[[1]][2]]
dt
    name name_final
1: foo123        foo
2: bar234        foo

我不知道 data.table 内部是如何工作的,但我猜该函数首先应用于整个 name 列,然后结果以某种方式被强制转换为向量,并且然后分配给新的 name_final 列。但是,我在这里期望的行为是逐行进行的。我可以通过添加虚拟 id 列来模拟此行为;

dt[, id := seq_along(name)]
dt[, name_final := regmatches(name, regexec(pattern, name))[[1]][2], by = list(id)]
dt
    name name_final id
1: foo123        foo  1
2: bar234        bar  2

为什么这不是默认行为?如果是这样,我猜想它与 data.table 的原子列而不是行有关,但我想了解那里发生了什么。

R 运行s 在逐行的基础上几乎没有任何内容。一次处理数据列总是更好,因此您几乎可以假设值的整个列向量将作为参数传递给您的函数。这是为 regmatches 列表中的每个项目提取第二个元素的方法

dt[, name_final := sapply(regmatches(name, regexec(pattern, name)), `[`, 2)]

sapply()Vectorize() 这样的函数可以 "fake" 对不应该 运行 在 [=18= 上的函数进行每行类型调用] 一次的数据。