非聚合函数的第一行

时间:2011-11-07 19:05:44

标签: r plyr

我使用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])})

2 个答案:

答案 0 :(得分: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条件时的通用访问;即,当您事先不知道by变量时。

答案 1 :(得分:1)

您可以使用:

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

当您返回向量时,将其作为data.frame重新组合在一起使每个条目成为一列。但是有不同的长度,因此它们并不都具有相同数量的列。通过将其包装在data.frame()中,您可以确保函数返回具有所需列的data.frame,而不是依赖于隐式(在这种情况下,错误)转换。此外,您可以在此构造中轻松命名新列。

更新:

鉴于你只想评估一次这个函数(这是合理的),那么你可以自己拉出第一行并对其进行操作。

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)))
})