我使用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 :(得分: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)))
})