使用分配给多个列的最佳方法是什么data.table?例如:
f <- function(x) {c("hi", "hello")}
x <- data.table(id = 1:10)
Run Code Online (Sandbox Code Playgroud)
我想做这样的事情(当然这种语法不正确):
x[ , (col1, col2) := f(), by = "id"]
Run Code Online (Sandbox Code Playgroud)
为了扩展它,我可能有很多列的名称存储在一个变量(比如说col_names)中,我想这样做:
x[ , col_names := another_f(), by = "id", with = FALSE]
Run Code Online (Sandbox Code Playgroud)
做这样的事的正确方法是什么?
可能重复:
可变地选择/分配data.table中的字段
在下面的示例中,我创建了一个列名为"x"和"v"的数据表
library('data.table')
DT <- data.table(x = c("b","b","b","a","a"), v = rnorm(5))
Run Code Online (Sandbox Code Playgroud)
我可以通过以下方式访问列'x'的值:
DT[ , x]
# [1] "b" "b" "b" "a" "a"
Run Code Online (Sandbox Code Playgroud)
但是如果我想通过传递变量来访问它,它就不起作用
temp <- "x"
DT[ , temp]
# [1] "x"
Run Code Online (Sandbox Code Playgroud)
将有多个列,我将只为其中几个选择值.我将通过R模块提供这些列名.
没关系,我明白了,它应该是:
DT[ , get(temp)]
Run Code Online (Sandbox Code Playgroud) data.table如果变量名存储在字符向量中,如何引用变量?例如,这适用于data.frame:
df <- data.frame(col1 = 1:3)
colname <- "col1"
df[colname] <- 4:6
df
# col1
# 1 4
# 2 5
# 3 6
Run Code Online (Sandbox Code Playgroud)
如何使用或不使用:=表示法对data.table执行相同的操作?显而易见的事情是dt[ , list(colname)]行不通的(我也没想到).
我正在尝试使用data.table来加速处理由几个较小的合并data.frames组成的大型data.frame(300k x 60).我是data.table的新手.到目前为止的代码如下
library(data.table)
a = data.table(index=1:5,a=rnorm(5,10),b=rnorm(5,10),z=rnorm(5,10))
b = data.table(index=6:10,a=rnorm(5,10),b=rnorm(5,10),c=rnorm(5,10),d=rnorm(5,10))
dt = merge(a,b,by=intersect(names(a),names(b)),all=T)
dt$category = sample(letters[1:3],10,replace=T)
Run Code Online (Sandbox Code Playgroud)
我想知道是否有比以下更有效的方法来总结数据.
summ = dt[i=T,j=list(a=sum(a,na.rm=T),b=sum(b,na.rm=T),c=sum(c,na.rm=T),
d=sum(d,na.rm=T),z=sum(z,na.rm=T)),by=category]
Run Code Online (Sandbox Code Playgroud)
我真的不想手工输入所有50列计算,而且eval(paste(...))似乎很笨拙.
我看了下面的例子,但对我的需求似乎有点复杂.谢谢
data.table是一个梦幻般的R包,我在我正在开发的库中使用它.到目前为止,一切都很顺利,除了一个并发症.data.table使用保存在变量中的名称来引用列(例如:对于数据帧),似乎要比使用常规数据帧更难(与传统数据帧相比colname="col"; df[df[,colname]<5,colname]=0).
也许最让事情变得复杂的是这种语法明显缺乏一致性data.table.在某些情况下,eval(colname)和get(colname),甚至c(colname)似乎工作.在其他方面,DT[,colname, with=F]是解决方案.然而在其他方面,例如,set()和subset()功能,我根本没有找到解决方案.最后,前面讨论了一个极端的,虽然也是非常常见的用例(以编程方式将列名称传递给data.table),并且建议的解决方案虽然显然正在完成他们的工作,但似乎并不特别可读......
也许我太复杂了?如果有人可以记下快速备忘单,以便data.table使用不同常见场景的变量来引用列名,我将非常感激.
更新:
提供的一些具体示例我可以硬编码列名:
x.short = subset(x, abs(dist)<=100)
set(x, which(x$val<10), "val", 0)
Run Code Online (Sandbox Code Playgroud)
现在假设distcol="dist",valcol="val".使用distcoland valcol,但不是dist和val?的最佳方法是什么?
我正在尝试向我添加列data.table,其中名称是动态的.另外,我需要by在添加这些列时使用参数.例如:
test_dtb <- data.table(a = sample(1:100, 100), b = sample(1:100, 100), id = rep(1:10,10))
cn <- parse(text = "blah")
test_dtb[ , eval(cn) := mean(a), by = id]
# Error in `[.data.table`(test_dtb, , `:=`(eval(cn), mean(a)), by = id) :
# LHS of := must be a single column name when with=TRUE. When with=FALSE the LHS may be a vector of column names or positions.
Run Code Online (Sandbox Code Playgroud)
另一种尝试:
cn <- "blah"
test_dtb[ , cn := mean(a), by = id, with …Run Code Online (Sandbox Code Playgroud) 我想计算data.table中每个列的平均值,按另一列分组.我的问题类似于关于SO的另外两个问题(一个和两个),但我不能将这些问题应用于我的问题.
这是一个例子:
library(data.table)
dtb <- fread(input = "condition,var1,var2,var3
one,100,1000,10000
one,101,1001,10001
one,102,1002,10002
two,103,1003,10003
two,104,1004,10004
two,105,1005,10005
three,106,1006,10006
three,107,1007,10007
three,108,1008,10008
four,109,1009,10009
four,110,1010,10010")
dtb
# condition var1 var2 var3
# 1: one 100 1000 10000
# 2: one 101 1001 10001
# 3: one 102 1002 10002
# 4: two 103 1003 10003
# 5: two 104 1004 10004
# 6: two 105 1005 10005
# 7: three 106 1006 10006
# 8: three 107 1007 10007
# 9: three …Run Code Online (Sandbox Code Playgroud) 我认为元编程在这里是正确的术语.
我希望能够使用data.table,就像在webapp中使用MySQL一样.也就是说,Web用户使用一些Web前端(例如Shiny服务器)来选择数据库,选择要过滤的列,选择要分组的列,选择要聚合的列和聚合函数.我想使用R和data.table作为查询,聚合等的后端.假设前端存在,R将这些变量作为字符串,并验证它们等.
我编写了以下函数来构建data.table表达式并使用R的parse/eval元编程功能来运行它.这是一种合理的方法吗?
我包括所有相关代码来测试这个.获取此代码(在读取安全性之后!)并运行test_agg_meta()来测试它.这只是一个开始.我可以添加更多功能.
但我的主要问题是我是否过度思考这一点.有没有更直接的方法来使用data.table,所有的输入都是事先确定的,而不需要求助于parse/eval元编程?
我也知道"with"声明和一些其他无糖功能方法,但不知道他们是否可以处理所有情况.
require(data.table)
fake_data<-function(num=12){
#make some fake data
x=1:num
lets=letters[1:num]
data=data.table(
u=rep(c("A","B","C"),floor(num/3)),
v=x %%2, w=lets, x=x, y=x^2, z=1-x)
return(data)
}
data_table_meta<-function(
#aggregate a data.table meta-programmatically
data_in=fake_data(),
filter_cols=NULL,
filter_min=NULL,
filter_max=NULL,
groupby_cols=NULL,
agg_cols=setdiff(names(data_in),groupby_cols),
agg_funcs=NULL,
verbose=F,
validate=T,
jsep="_"
){
all_cols=names(data_in)
if (validate) {
stopifnot(length(filter_cols) == length(filter_min))
stopifnot(length(filter_cols) == length(filter_max))
stopifnot(filter_cols %in% all_cols)
stopifnot(groupby_cols %in% all_cols)
stopifnot(length(intersect(agg_cols,groupby_cols)) == 0)
stopifnot((length(agg_cols) == length(agg_funcs)) | (length(agg_funcs)==1) | (length(agg_funcs)==0))
}
#build the command
#defaults
i_filter=""
j_select=""
n_agg_funcs=length(agg_funcs)
n_agg_cols=length(agg_cols)
n_groupby_cols=length(groupby_cols)
if (n_agg_funcs == 0) …Run Code Online (Sandbox Code Playgroud) 该包data.table具有一些特殊的语法,需要使用表达式作为i和j参数.
这对于一个接受并将参数传递给数据表的写函数有一些影响,正如常见问题解答第1.16节中所解释的那样.
但我无法弄清楚如何采取这一额外的水平.
这是一个例子.假设我想编写一个包装函数foo(),它对我的数据进行特定的汇总,然后是第二个plotfoo()调用foo()并绘制结果的包装器:
library(data.table)
foo <- function(data, by){
by <- substitute(by)
data[, .N, by=list(eval(by))]
}
DT <- data.table(mtcars)
foo(DT, gear)
Run Code Online (Sandbox Code Playgroud)
好的,这是有效的,因为我得到了我的表格结果:
by N
1: 4 12
2: 3 15
3: 5 5
Run Code Online (Sandbox Code Playgroud)
现在,我在写作的时候尝试的plotfoo()却是一样但是我悲惨地失败了:
plotfoo <- function(data, by){
by <- substitute(by)
foo(data, eval(by))
}
plotfoo(DT, gear)
Run Code Online (Sandbox Code Playgroud)
但这次我收到一条错误消息:
Error: evaluation nested too deeply: infinite recursion / options(expressions=)?
Run Code Online (Sandbox Code Playgroud)
好的,所以eval()导致了问题.我们将其删除:
plotfoo <- function(data, by){
by …Run Code Online (Sandbox Code Playgroud) 我是R中data.table包的新用户.我试图给"group by"命令创建的新列命名
> DT = data.table(x=rep(c("a","b"),c(2,3)),y=1:5)
> DT
x y
1: a 1
2: a 2
3: b 3
4: b 4
5: b 5
> DT[,{z=sum(y);z+3},by=x]
x V1
1: a 6
2: b 15
Run Code Online (Sandbox Code Playgroud)
另外,是否可以在一个命令中执行多个操作组,这将导致类似于:
x V1 V2
1: a 6 something
2: b 15 something
Run Code Online (Sandbox Code Playgroud)谢谢