2016-06-10 106 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]