首先,让我们看一下 data.table
包中的 setkey
函数是如何工作的:
function (x, ..., verbose = getOption("datatable.verbose"))
{
if (is.character(x))
stop("x may no longer be the character name of the data.table. The possibility was undocumented and has been removed.")
cols = getdots()
if (!length(cols))
cols = colnames(x)
else if (identical(cols, "NULL"))
cols = NULL
setkeyv(x, cols, verbose = verbose)
}
因此,当您执行以下操作时:
require(data.table)
dt <- data.table(ID=c(1,1,2,2,3), y = 1:5)
setkey(dt, ID)
它调用了data.table
内部的函数getdots
(也就是说,它没有被导出)。让我们来看看这个函数:
function ()
{
as.character(match.call(sys.function(-1), call = sys.call(-1),
expand.dots = FALSE)$...)
}
那么,这是做什么的?它将您在 setkey
中输入的参数提取,并使用 match.call
分别提取参数。也就是说,对于此示例情况,match.call
的参数将是:
setkey(x = dt, ... = list(ID))
由于它是一个列表,因此您可以使用$...
访问...
参数以获取值为ID
的1个元素的列表,并将此列表转换为字符向量"ID"
(通过as.character
),然后setkey
将其传递给setkeyv
来设置键。
那么为什么在函数内部写setkey(table, key)
不起作用呢?
这正是由于setkey/getdots
的方式。 setkey
函数旨在接受第一个参数(即)之后的任何参数,然后将...
参数作为字符返回。
也就是说,如果你提供setkey(dt, key)
,那么它将返回cols <- "key"
。如果你提供setkey(dt, e)
,它会返回cols <- "e"
。它不会查找"key"是否是现有变量,如果是,则替换变量的值。它所做的就是将您提供的值(无论是符号还是字符)转换回字符。
当然,在您的情况下,这样做行不通,因为您希望在setkey
中提供key
= ID的值。至少我想不到一种方法可以这样做。
如何解决这个问题?
正如@agstudy已经提到的,最好/最简单的方法是传递"ID"
并使用setkeyv
。但是,如果您真的坚持要使用f("table.csv", ID)
,那么您可以这样做:
f <- function(path, key) {
table = data.table(read.delim(path, header=TRUE))
e = as.character(match.call(f)$key)
setkeyv(table, e)
return(table)
}
在这里,您首先使用 match.call
获取与参数 key
相对应的值,然后将其转换为 character
,然后将其传递给 setkeyv
。
简而言之,setkey
内部使用 setkeyv
。并且在我看来,当您已经知道需要设置键的 data.table
的列名时,setkey
是一个方便的函数。希望这有所帮助。
data.table
不是一个函数。 - Scott Ritchiesetkeyv
并将 ID 给定为字符? - agstudydata.table
包。我刚刚进行了编辑并添加了标签。 - Arun