首先,我们来看看如何setkey
函数做的事情来自data.table
包裹:
# setkey function
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)
它调用该函数getdots
这是内部的data.table
(也就是说,它不被导出)。让我们看一下这个函数:
# 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))
由于它是一个列表,您可以访问...
参数与$...
获取包含 1 个元素及其值的列表ID
并将此列表转换为字符as.character
结果是"ID"
(字符向量)。进而setkey
将其传递给setkeyv
内部设置按键。
现在为什么当你写的时候这不起作用setkey(table, key)
在你的函数里面?
正是因为这样的方式setkey/getdots
是。这setkey
函数被设计为在第一个参数之后接受任何参数(这是一个data.table
)然后返回...
作为一个角色的论证。
也就是说,如果你给setkey(dt, key)
然后它会返回cols <- "key"
。如果你给setkey(dt, e)
,它会回馈cols <- "e"
。它不会查找“key”是否是现有变量,如果是,则替换该变量的值。它所做的只是将您提供的值(无论是符号还是字符)转换回字符。
当然,这对你的情况不起作用,因为你想要的值key
= 提供的 IDsetkey
。至少我想不出办法来做到这一点。
如何解决这个问题?
正如@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
。恕我直言,当您已经知道列名时,setkey 是一个方便使用的函数。data.table
您需要为其设置密钥。希望这可以帮助。