R中的ddply函数:应用if和ifelse函数

6
我正在尝试使用plyr包中的ddply将函数应用于数据框,但我得到了一些我不理解的结果。我有三个问题关于这些结果。
给定:
mydf<- data.frame(c(12,34,9,3,22,55),c(1,2,1,1,2,2)
                  , c(0,1,2,1,1,2))
colnames(mydf)[1] <- 'n'
colnames(mydf)[2] <- 'x'
colnames(mydf)[3] <- 'x1'

我的df长这样:
   n x x1
1 12 1  0
2 34 2  1
3  9 1  2
4  3 1  1
5 22 2  1
6 55 2  2

问题1:

如果我这样做:

k <- function(x) {
  mydf$z <- ifelse(x == 1, 0, mydf$n)
  return (mydf)
}
mydf <- ddply(mydf, c("x") , .fun = k, .inform = TRUE)

我得到了以下错误:
Error in `$<-.data.frame`(`*tmp*`, "z", value = structure(c(12, 34, 9,  : 
  replacement has 3 rows, data has 6
Error: with piece 1: 
   n x x1
1 12 1  0
2  9 1  2
3  3 1  1

我无论将要拆分的变量指定为c("x"), "x"还是 .(x),都会出现这个错误。我不明白为什么会出现这个错误信息。
问题 #2
但是,我真正想做的是设置一个if/else函数,因为我的数据集有变量x1、x2、x3和x4,我也想考虑这些变量。但是当我尝试一些简单的东西时,比如:
j <- function(x) {
  if(x == 1){
    mydf$z <- 0
  } else {
    mydf$z <- mydf$n
  }
  return(mydf)
  }

mydf <- ddply(mydf, x, .fun = j, .inform = TRUE)

我得到:
Warning messages:
1: In if (x == 1) { :
  the condition has length > 1 and only the first element will be used
2: In if (x == 1) { :
  the condition has length > 1 and only the first element will be used

问题 #3

我对于何时使用 function() 以及何时使用 function(x) 感到困惑。无论是在 j() 还是 k() 中使用 function() 都会给我不同的错误:

Error in .fun(piece, ...) : unused argument (piece)
Error: with piece 1: 
    n x x1  z
1  12 1  0 12
2   9 1  2  9
3   3 1  1  3
4  12 1  0 12
5   9 1  2  9
6   3 1  1  3
7  12 1  0 12
8   9 1  2  9
9   3 1  1  3
10 12 1  0 12
11  9 1  2  9
12  3 1  1  3

“在列z不正确的情况下。 然而,我看到很多函数被写成function()。”
“我非常感谢任何可以帮助我的评论。”

@Metrics 这两个问题都涉及到了 ddply 和 ifelse,除此之外,除了这一点,它们还有什么被认为是重复的呢? - joran
@Joran:除了这两个之外,没有其他的 :) - Metrics
请提供可重现的示例和清晰的解释,这样更有利于编程。 - Simon O'Hanlon
1个回答

11

这里需要解释的内容很多。让我们从最简单的情况开始。在您的第一个示例中,您只需要:

mydf$z <- with(mydf,ifelse(x == 1,0,n))

一个等效的ddply解决方案可能如下所示:

ddply(mydf,.(x),transform,z = ifelse(x == 1,0,n))

你似乎最大的困惑来源是不理解 ddply 函数中传递的参数。

考虑你的第一次尝试:

k <- function(x) {
  mydf$z <- ifelse(x == 1, 0, mydf$n)
  return (mydf)
}

ddply 的工作方式是根据列 x 中的值将 mydf 拆分成几个较小的数据框。这意味着每次 ddply 调用 k 时,传递给 k 的参数是一个数据框,具体来说,是您原始数据框的一个子集。

因此,在 k 内部,xmydf 的一个子集,带有所有的列。您不应该尝试从 k 内部修改 mydf。请修改 x ,然后返回修改后的版本。(如果必须,但上面显示的选项更好。)因此,我们可以像这样重新编写您的 k :

k <- function(x) {
  x$z <- ifelse(x$x == 1, 0, x$n)
  return (x)
}

请注意,您在将x用作k的参数以及我们某列的名称时,创建了一些令人困惑的内容。


@baptiste 我知道。这就是为什么我的第一个选项只使用了 ifelse。但既然我们在这里,他们也可以学会如何使用 ddply - joran
我知道你知道,你知道我知道;新版本解释更多。 - baptiste
@baptiste 抱歉,我不知道我不知道你知道我知道,你懂的? - joran
@joran非常感谢您的回复。是的,我的列名为x并不好。修正这个问题帮助我更清晰地看待事物。我需要编写和命名一个函数,因为在我的if语句后面有5个else(此示例已简化)。您的答案解决了我的问题。我现在正在重新阅读它,因为它对ddply和参数/函数的解释非常清晰。感谢您抽出时间写下您的回复。 - SCallan

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