2016-06-10 74 views
6

组内转置的向量什么是生成一个data.table单独的列的函数返回的元素,由组计算的data.table方法?data.table

考虑data.table:

library(data.table) 
data(iris) 
setDT(iris) 

如果函数range(),我想类似的输出:

iris[, .(min_petal_width = min(Petal.Width), 
     max_petal_width = max(Petal.Width) 
     ), keyby = Species] # produces desired output 

但使用range()功能。

我可以使用dcast,但它的丑陋:

dcast(
    iris[, .(petal_width = range(Petal.Width), 
      value = c("min_petal_width", "max_petal_width")), 
     keyby = Species], 
    Species ~ value, value.var = "petal_width") 

我希望有一个更简单的表达,沿着线:

iris[, (c("min_petal_width","max_petal_width")) = range(Petal.Width), 
     keyby = Species] # doesn't work 

回答

5

你的做法是非常接近的。请记住,您需要将一个列表提供给data.table,并且会很乐意接受它。因此,你可以使用:

iris[, c("min_petal_width","max_petal_width") := as.list(range(Petal.Width)), 
    by = Species] 

我误解了问题。既然要汇总的结果,而不是增加新的栏目,你可以使用

cols <- c("min_petal_width", "max_petal_width") 
iris[, setNames(as.list(range(Petal.Width)), cols), keyby = Species] 

但我敢肯定有一个还有其他一些data.table方法。

+2

这并不返回一个新的data.table,但它会修改虹膜就地data.table增加两列,它 – digEmAll

+0

@digEmAll,哦,你是对的,当然。 –

6

你也可以这样做:

dt[, lapply(list(min=min, max=max), function(f) f(Petal.Width)), by=Species] 
#  Species min max 
# 1:  setosa 0.1 0.6 
# 2: versicolor 1.0 1.8 
# 3: virginica 1.4 2.5 
2

如果可读性和简洁是对你真的很重要,我会定义一个自定义的功能或二进制运算符,然后您可以轻松地在data.table子表达式中使用,例如:

# custom function 
.nm <- function(v,vnames){ 
    `names<-`(as.list(v),vnames) 
} 
# custom binary operator 
`%=%` <- function(vnames,v){ 
    `names<-`(as.list(v),vnames) 
} 

# using custom function 
iris[, .nm(range(Petal.Width),c("min_petal_width", "max_petal_width")), keyby = Species] 

# using custom binary operator 
iris[, c("min_petal_width", "max_petal_width") %=% range(Petal.Width), keyby = Species]