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

时间:2015-01-22 16:05:01

标签: r data.table

我有一个包含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而不是行的原子列有关,但我想了解那里发生了什么。

1 个答案:

答案 0 :(得分:3)

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

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

sapply()Vectorize()等功能可以&#34;假&#34;对于不能一次在矢量/数据列表上运行的函数的每行类型调用。