在遍历data.tables列表时如何对行进行子集化?

时间:2019-03-15 10:07:10

标签: r data.table

我正在R中处理大量data.tables。我已将data.tables放在一个列表中,如下例所示:

dt1 <- data.table(v1 = c("a","a","a"), v2 = 1:3)
dt2 <- data.table(v1 = c("notes","a","a"), v2 = 1:3)
dt3 <- data.table(v1 = c("notes","a","a"), v2 = 1:3)

dt_list <- list(dt1, dt2, dt3)

我想对列表中的每个data.table执行一组操作。例如,在v1中删除带有“注释”的行,然后添加新列。

列操作按我的预期进行(尽管在我的环境中出现了一个新的data.table dt):

for (dt in dt_list) {
  dt <- dt[, newvar := "new"]
} 

dt2
          v1 v2 newvar
    1: notes  1    new
    2:     a  2    new
    3:     a  3    new

但是,行操作似乎没有以相同的方式编辑data.tables:

for (dt in dt_list) {
  dt <- dt[v1 != "notes", ]
}

dt2
          v1 v2 newvar
    1: notes  1    new
    2:     a  2    new
    3:     a  3    new

for循环中的代码确实适用于单个data.table,因此问题似乎是由于使用for和/或list引起的:

dt2 <- dt2[v1 != "notes"]
dt2
       v1 v2 newvar
    1:  a  2    new
    2:  a  3    new

我已经针对其他行操作对此进行了测试,并且遇到了相同的问题。有没有一种方法可以删除v1中列表中所有data.tables包含“注释”的行?

谢谢。

1 个答案:

答案 0 :(得分:3)

data.table包允许您使用set函数或:=运算符通过引用来更改对象的值。赋值运算符<-没有这种默认行为。因此,如果您将第一个循环替换为:

for (dt in dt_list) {
  dt[, newvar := "new"]
} 

它将具有相同的效果。您只需使用dt即可更改:=。另一方面,如果您不使用它,更改将不会反映在原始数据中。目前,我不相信您可以使用data.table通过引用来删除行或对行进行子集设置,因此您需要按照@jogo或@markus的建议创建一个新列表

dt_list2<-lapply(dt_list, function(dt) dt[v1 != "notes"])