使用循环在ddply中创建新变量

10

我正在使用ddply来聚合和总结数据框变量,我有兴趣遍历我的数据框列表以创建新变量。

new.data <- ddply(old.data, 
                  c("factor", "factor2"),
                  function(df)
                    c(a11_a10 = CustomFunction(df$a11_a10),
                      a12_a11 = CustomFunction(df$a12_a11),
                      a13_a12 = CustomFunction(df$a13_a12),
                      ...
                      ...
                      ...))

我是否可以在ddply中插入循环,以避免编写每个新摘要变量,例如:

for (i in 11:n) {
  paste("a", i, "_a", i - 1) = CustomFunction(..... )
}
我知道这不是实际操作的方式,但我只是想展示一下我的思路。在我调用ddply的函数中或通过列表的方式,有没有办法实现这个想法?
更新:因为我是新用户,无法回答自己的问题:
我的答案涉及到Nick的回答和Ista的评论。
func <- function(old.data, min, max, gap) {
  varrange <- min:max
  usenames <- paste("a", varrange, "_a", varrange - gap, sep="")
  new.data <- ddply(old.data,
                    .(factor, factor2),
                    colwise(CustomFunction, c(usenames)))
}

你可能需要使用 transform() 或者 summarize()summarize 的帮助页面中有一些很好的例子。 - Chase
@Chase - 关于总结,我可以使用以下代码:for (i in 11:n) with(old.data, summarize(old.data[, paste("a", i, "_a", i - 1, sep="")], llist(factor, factor2), CustomFunction)) - Iris Tsui
1
如果您能提供一个可重现的示例,那么对于您的潜在帮助者来说,这将使生活变得更加容易。在没有工作示例的情况下,我只能猜测您是否正在寻找?colwise(请参阅与ddply一起使用的示例)。 - Ista
@ Ista - 谢谢,colwise正是我在了解到Nick将变量名初始加载到内存后所寻找的东西。 - Iris Tsui
+1 @Casey。非常优雅。 - Ramnath
3个回答

7

在@Nick的出色答案基础上,这里提供一种解决问题的方法

foo <- function(df){
  names   = paste("a", 11:n, "_a", 10:(n-1), sep = "")
  results = sapply(df[,names], CustomFunction)
}

new.data = ldply(dlply(old.data, c("factor", "factor2")), foo)

这里是一个使用ggplot2中的tips数据集的示例应用程序。假设我们想要通过sexsmoker的组合来计算tiptotal_bill的平均值,以下是代码的工作方式:

foo = function(df){names = c("tip", "total_bill"); sapply(df[,names], mean)}
new = ldply(dlply(tips, c("sex", "smoker")), foo)

它会生成下面所示的输出。
         .id      tip total_bill
1  Female.No 2.773519   18.10519
2 Female.Yes 2.931515   17.97788
3    Male.No 3.113402   19.79124
4   Male.Yes 3.051167   22.28450

这是你要找的吗?

@ Ramnath- 这正是我要找的,除了我希望因子/ID变量保持分离。我相信我在更新中给出的答案将允许我这样做,但您已经很好地回答了我的问题,并将示例制作成一个函数,我将尝试进行适应。谢谢。 - Iris Tsui
@Casey。你的回答更加优雅!我已经点赞了,如果可以的话,我会给它+2。干得好! - Ramnath
所有这些都可以使用“colwise”在一行中完成。请参见我的答案。 - Andrie

4

如果我理解您的意思正确,您基本上想将自定义函数应用于 ddply 数据框中的每一列。

好消息是有一个 ddply 函数可以完全实现这一点。这意味着解决您的问题只需要一行代码:

在 @Ramnath 的优秀示例基础上进行改进:

library(ggplot2)
customfunction <- mean
ddply(tips, .(sex, smoker), numcolwise(customfunction))

     sex smoker total_bill      tip     size
1 Female     No   18.10519 2.773519 2.592593
2 Female    Yes   17.97788 2.931515 2.242424
3   Male     No   19.79124 3.113402 2.711340
4   Male    Yes   22.28450 3.051167 2.500000

这种方法有效的原因是colwise将适用于向量的函数转换为适用于数据框中列的函数。有两个变体:numcolwise仅适用于数字列,而catcolwise适用于分类列。有关更多信息,请参见?colwise
编辑:我理解您可能不希望将该函数应用于数据框中的所有列。但是,我发现这种语法非常简单,我的一般方法是修改传递给ddply的数据框。例如,以下修改后的示例将tips子集排除了一些列。解决方案仍然是一行代码:
ddply(tips[, -2], .(sex, smoker), numcolwise(customfunction))

     sex smoker total_bill     size
1 Female     No   18.10519 2.592593
2 Female    Yes   17.97788 2.242424
3   Male     No   19.79124 2.711340
4   Male    Yes   22.28450 2.500000

只有在将函数应用于除拆分所用列之外的所有列时,此方法才有效。如果这确实是 OP 的情况,则这将是最佳解决方案。否则,我认为 OP 提出的解决方案更通用。 - Ramnath
@Ramnath,同意你的观点,说得好。不过,在我的工作流程中,我更喜欢对数据框进行简单的子集操作,而不是进行一些比较复杂的编码。我已经编辑了我的答案以反映这一点。 - Andrie
2
colwise具有一个“cols”参数,该参数接受变量名称的字符向量... - hadley

3
按步骤执行:
varrange<-11:n
usenames<-paste("a", varrange, "_a", varrange - 1, sep="")
results<-sapply(usenames, function(curname){CustomFunction(df[,curname])})
names(results)<-usenames

你想要的是这个吗?


谢谢您的回复,但这不是我要找的。我希望最终得到一个数据框,其中包括每个“factor”和“factor2”组合的唯一观察值,并且对于我的两个因素的每个唯一组合,都有来自我的CustomFunction的“a”变量的输出。 - Iris Tsui
基本上我正在寻找ddply功能,但是希望使用循环或列表方法自动创建变量。 - Iris Tsui

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接