对于R中的循环函数

时间:2014-08-27 19:39:13

标签: r function for-loop dataframe

我一直在努力弄清楚为什么我没有从我的函数中将正确的值返回到我的数据框。我想循环遍历数据框的向量,并通过向量元素内的计算创建一个新列。这就是我所拥有的:

# x will be the data frame's vector
y <- function(x){
 new <- c()
 for (i in x){
  new <- c(new, x[i] - x[i+1])
 }
 return (new)
}

所以这里我想创建一个新的向量,它返回从当前元素中减去的下一个元素。现在,当我将它应用到我的数据框

df$new <- lapply(df$I, y)

我得到了所有的NA。我知道我错过了一些完全明显的东西......

另外,如果df $ ID发生变化,我将如何执行重置自身的功能,这样我就不会从两个不同的df $ ID中减去元素?例如,我的数据框将具有

ID  I   Order   new
1001    5   1   1
1001    6   2   -2
1001    4   3   -2
1001    2   4   NA
1005    2   1   6
1005    8   2   0
1005    8   3   -2
1005    6   4   NA

谢谢!

3 个答案:

答案 0 :(得分:2)

避免循环并使用diff。这里的一切都是矢量化的,所以很容易。

df$new <- c(diff(df$I), NA)

但我不了解你的榜样结果。为什么有些0值已更改为NA而有些值未更改为8-2?我不应该6而不是-6而不是0?我认为需要澄清。

如果需要将NA值更改为df$new[df$new == 0] <- NA ,请在上述代码后执行以下操作。

within(df, { new <- c(diff(I), NA); new[new == 0] <- NA })

返回新数据框的完整过程的一行,可以是

> M <- do.call(rbind, Map(function(x) { x$z <- c(diff(x$I), NA); x }, 
                          split(dat, dat$ID)))
> rownames(M) <- NULL
> M
    ID I Order  z
1 1001 5     1  1
2 1001 6     2 -2
3 1001 4     3 -2
4 1001 2     4 NA
5 1005 2     1  6
6 1005 8     2  0
7 1005 8     3 -2
8 1005 6     4 NA

更新:关于您的评论,我的更新后的答案如下:

{{1}}

答案 1 :(得分:1)

而不是循环,你最好使用数学的矢量版本。确切的索引将取决于你想对最后一个值做什么...(注意这一行不会放在你的for循环中,而只是给出结果。)

df$new = c(df$I[-1],NA) - df$I

在这里,您将从省略第一个值df$I的移位版本中减去原始[-1],并在末尾添加NA

每条评论的编辑:如果您不想在df$ID之间减去,则可以在减法后删除该子单元格:

 df$new[df$ID != c(df$ID[-1],NA)] = NA

答案 2 :(得分:1)

dplyr库使您可以非常轻松地为每个级别的分组变量单独执行操作,在您的情况下ID。我们可以使用diff作为@Richard Scriven建议,并使用dplyr::mutate添加新列。

> library(dplyr)
> df %>% group_by(ID) %>% mutate(new2 = c(diff(I), NA))
Source: local data frame [8 x 5]
Groups: ID

    ID I Order new new2
1 1001 5     1   1    1
2 1001 6     2  -2   -2
3 1001 4     3  -2   -2
4 1001 2     4  NA   NA
5 1005 2     1   6    6
6 1005 8     2   0    0
7 1005 8     3  -2   -2
8 1005 6     4  NA   NA