2011-11-07 22 views
1

我使用ddply來避免冗餘計算。非集合函數的第一行

我經常處理分割子集內保存的值,並進行非聚合分析。所以爲了避免這個(一個玩具的例子):

ddply(baseball,.(id,year),function(x){paste(x$id,x$year,sep="_")}) 

Error in list_to_dataframe(res, attr(.data, "split_labels")) : 
    Results do not have equal lengths 

我必須採取每個迷你數據框的第一行。

ddply(baseball,function(x){paste(x$id[1],x$year[1],sep="_")}) 

有沒有不同的方法或我應該使用的幫手?這個語法看起來很尷尬。

-

注:貼在我的例子是作秀 - 不要把它文生義。想象一下,這是實際的功能:

ddply(baseball,function(x){the_slowest_function_ever(x$id[1],x$year[1])}) 
+0

我很驚訝沒有辦法從函數 –

+0

內部獲得.variables引發的問題:https://github.com/hadley/plyr/issues/68 –

回答

1

你可以使用:

ddply(baseball, .(id, year), function(x){data.frame(paste(x$id,x$year,sep="_"))}) 

當您返回一個載體,把它重新走到一起作爲一個data.frame使得每個條目列。但是有不同的長度,所以它們並不都具有相同的列數。通過將它包裝在data.frame()中,可以確保函數返回一個data.frame,它具有您想要的列而不是依賴隱式(在這種情況下是錯誤的)轉換。此外,您可以在此構造中輕鬆地命名新列。

UPDATE:

由於您只需要一次評估功能(這是合理的),那麼你可以拉頭排出來本身和上進行操作。

ddply(baseball, .(id, year), function(x) { 
    x <- x[1,] 
    paste(x$id, x$year, sep="_") 
}) 

這將(單獨)每個id/year組合只有一行。如果您希望它的行數與原始行數相同,那麼您可以將它與前面的想法結合起來。

ddply(baseball, .(id, year), function(x) { 
    firstrow <- x[1,] 
    data.frame(label=rep(paste(firstrow$id, firstrow$year, sep="_"), nrow(x))) 
}) 
3

在這種情況下,您可能會發現data.table更容易一些,速度更快。 .()變量相對應的是by=

DT[, { paste(id,year,sep="_") }, by=list(id,year) ] 

DT[, { do.call("paste",.BY) }, by=list(id,year) ] 

我已經展示了{}說明你可以把任何(多線)匿名身體j(而不是函數) ,但在這些簡單的例子中,你不需要{}

爲了提高速度和方便性,分組變量在每個組的範圍內(這似乎是你要問的)的長度爲1。 .BY也包含一個列表對象中的分組變量,以便在編程上動態確定標準時通用訪問;即,當您事先不知道變量by時。