如果列名是字符串,则按行选择

时间:2017-03-14 12:28:56

标签: r data.table

我必须处理大量数据集,这就是我必须使用data.table包的原因。我想只选择在给定列中具有适当值的行。

dt <- data.table(a = rep(c("A", "B", "C"), 3), 
                 b = 1:9)
n <- c("A", "C")

我能做什么:

dt[ a %in% n]
   a b
1: A 1
2: C 3
3: A 4
4: C 6
5: A 7
6: C 9

如果我之前不知道列的名称并从函数字符串中获取该怎么办?我试过了:

dt[ "a" %in% n]
Empty data.table (0 rows) of 2 cols: a,b

dt[ "a" %in% n, with  = F]
Error in `[.data.table`(dt, "a" %in% n, with = F) : 
  j must be provided when with=FALSE

dt[ as.name("a") %in% n ]
Error in match(x, table, nomatch = 0L) : 
  'match' requires vector arguments

问题 - 是否可以在这样的任务中使用字符串?

2 个答案:

答案 0 :(得分:1)

可以通过各种方式实现这一目标

使用连接(将返回有序结果,而不对dt进行排序)

dt[.(n), on = "a"] 

或(在排序dt时也将返回有序结果)

setkeyv(dt, "a")[.(n)]

或使用eval / as.name(将返回未排序的结果)

dt[eval(as.name("a")) %in% n]

或使用列表子集(将返回未排序的结果)

dt[dt[["a"]] %in% n]

您可能需要考虑几点。

在v 1.9.4中,data.table包引入了二级索引。这意味着当您进行矢量扫描(==%in%)时,它会创建某种排序或键(与您明确使用setkey时的情况类似)第一次运行有点慢,但下次在此列中搜索匹配时会显着提高性能。

但是,并非在所有情况下都会(永久)设置辅助密钥。在某些情况下,它始终是一个简单的矢量扫描(例如dt[eval(as.name("a")) %in% n, verbose = TRUE]dt[get('a') %in% n]dt[dt[["a"]] %in% n, verbose = TRUE]),如果您只运行一次,它将会更快。在某些情况下,将在每次运行中创建一个ad-hoc索引(例如dt[n, on = "a", verbose = TRUE],但如果它已经存在,也将使用索引),这是次优的,而在某些情况下是永久密钥或辅助密钥将被设置(例如setkeyv(dt, "a")[.(n), verbose = TRUE]或@Frank dt[eval(substitute(col %in% n, list(col=as.name("a")))), verbose = TRUE]

提出的建议

答案 1 :(得分:0)

使用get功能

dt[get('a') %in% n]

如果colname存储在另一个变量中,它也有效:

temp <- 'a'
dt[get(temp) %in% n]