【发布时间】:2017-07-11 14:09:31
【问题描述】:
在评估data.table(与dplyr)的实用性时,一个关键因素是在函数和循环中使用它的能力。
为此,我修改了本文中使用的代码 sn-p:data.table vs dplyr: can one do something well the other can't or does poorly?,这样,它就变成了数据集,而不是硬编码的数据集变量名称(“钻石”数据集的“切割”和“价格”变量) -agnostic - cut-n-paste 准备好在任何函数或循环中使用(当我们事先不知道列名时)。
这是原始代码:
library(data.table)
dt <- data.table(ggplot2::diamonds)
dt[cut != "Fair", .(mean(price),.N), by = cut]
这是它与数据集无关的等价物:
dt <- data.table(diamonds)
nVarGroup <- 2 #"cut"
nVarMeans <- 7 #"price"
strGroupConditions <- levels(dt[[nVarGroup]])[-1] # "Good" "Very Good" "Premium" "Ideal"
strVarGroup <- names(dt)[nVarGroup]
strVarMeans <- names(dt)[nVarMeans]
qAction <- quote(mean(get(strVarMeans))) #! w/o get() it does not work!
qGroup <- quote(get(strVarGroup) %in% strGroupConditions) #! w/o get() it does not work!
dt[eval(qGroup), .(eval(qAction), .N), by = strVarGroup]
注意(感谢下方回复):如果需要通过引用改变变量值,需要使用(),而不是get(),如下图:
strVarToBeReplaced <- names(dt)[1]
dt[eval(qGroup), (strVarToBeReplaced) := eval(qAction), by = strGroup][]
现在:您可以剪切并粘贴以下代码以满足您的所有循环需求:
for(nVarGroup in 2:4) # Grouped by several categorical values...
for(nVarMeans in 5:10) { # ... get means of all numerical parameters
strGroupConditions <- levels(dt[[nVarGroup]])[-1]
strVarGroup <- names(dt)[nVarGroup]
strVarMeans <- names(dt)[nVarMeans]
qAction <- quote(mean(get(strVarMeans)))
qGroup <- quote(get(strVarGroup) %in% strGroupConditions)
p <- dt[eval(qGroup), .(AVE=eval(qAction), COUNT=.N), by = strVarGroup]
print(sprintf("nVaGroup=%s, nVarMeans=%s: ", strVarGroup, strVarMeans))
print(p)
}
我的第一个问题:
上面的代码虽然实现了所需的功能/循环需求,但看起来非常复杂。 - 它使用不同的多个(可能不一致的)非直观技巧,例如()、get()、quote()/eval()、[[]] 的组合。对于如此直接的需求来说似乎太多了......
还有其他更好的方法来访问和修改循环中的 data.tables 值吗? 或许使用on=、lapply/.SD/.SDcols?
请在下面分享您的想法。本次讨论旨在补充和巩固其他帖子中的相关内容(例如此处列出的:How can one work fully generically in data.table in R with column names in variables)。最终,最好创建一个专用的小插图,以便在 functions 和 loops 中使用 data.table。
第二个问题:
dplyr 是否更容易实现此目的? - 但是,对于这个问题,我设置了一个单独的帖子:Is dplyr easier than data.table to be used within functions and loops?。
【问题讨论】:
-
如果您愿意放弃欺骗或错误的列名和/或先清理它们,我想这更容易。
-
建议:发布一个新的 qn 比更改以前的 qn 更好,因为新的 qn 不会获得太多可见性。试试
dt[eval(qGroup), (strVarToBeReplaced) := 999, by = strGroup][] -
我不明白你的问题。您的“与数据集无关”的代码比直接使用 data.table 更通用吗?
-
您提到
[[]]在data.table小插曲中没有得到很好的描述。但是,DT[["v"]]包含在?data.table的示例部分,“以 data.frame 方式选择列”,注释“与 DT[, v] 相同,但速度更快”。所以,这似乎是首选的方式 -
问题不在于缺少文档(例如 [[]] 上的 .我们所有人都可以轻松地重用 stackoverflow.com 上提供的内容 - 只需简单的剪切粘贴即可,无需弄清楚如何用我们的变量替换“硬编码”变量名。想象一下 - 如果我们在示例中不使用“硬编码”名称变量,而是始终使用与数据集无关的代码,那么使用彼此的代码共同开发开源库会变得多么容易......干杯!
标签: r function loops data.table dplyr