在迭代for循环时保留对R数据帧的更改

时间:2013-11-09 18:35:13

标签: r loops

我是Stackexchange的新手,所以如果我错误地提出这个问题,我会提前道歉。

这是背景。我试图根据春季的最后一天确定小麦的推荐种植日期,在干燥的夏季开始之前,人们可以合理地预计会看到至少10次降雨。

我有一个如下所示的数据集:

    Site   Date Year DayOfYear DayofRun AveTemp MaxTemp MinTemp Precip TotPre
1 EelRiver 1/1/02 2002         1        1    53.6      57      51   1.01     NA
2 EelRiver 1/2/02 2002         2        2    52.5      64      43   1.30     NA
3 EelRiver 1/3/02 2002         3        3    46.6      60      42   0.56     NA
4 EelRiver 1/4/02 2002         4        4    45.7      57      41   0.00     NA
5 EelRiver 1/5/02 2002         5        5    51.0      57      46   0.53     NA
6 EelRiver 1/6/02 2002         6        6    57.9      60      55   1.70     NA

我想要做的是在TotPre列中填充从该日期到8月1日的总降雨量。

我知道,理想情况下,我会避免使用显式循环,但我感到困惑的是,似乎我需要计算一个根据我正在使用的观察而变化的子集的总和。所以,使用for循环,我试图这样做:

eelriverdata <- read.csv(file="EelRiverCamp.csv",head=TRUE,sep=",")

for (i in nrow(eelriverdata)) {

    tempYear <- eelriverdata[i,"Year"]
    AugIndex <- which(eelriverdata[,"Year"]==tempYear & eelriverdata[,"DayOfYear"] == 213)

    if (i < AugIndex) {
        Tot <- sum(eelriverdata[i:AugIndex,"Precip"])
        eelriverdata$TotPre[i] <- Tot
    }

    else {eelriverdata$TotPre[i] <- 0}

}

我遇到的问题是,只有TotPre中的最后一次观察才会在执行循环结束时填充,剩下的值保持为NA。在for循环的每次迭代中,值丢失或被覆盖的地方都会发生一些事情。我做了一些研究,但除了神秘的信息之外,还可以找到除了循环对数据框做出“意外事情”的神秘信息。

那么,有谁知道:

a)如何通过迭代继续对数据框进行更改?我很想知道在使用循环操作数据帧时我可能会遇到的“意想不到的事情”。

和/或

b)更优雅的解决方案。在做任何非常复杂的事情时,我很难使用apply,ddply等,也许我可以从这个例子中学习。

谢谢!

贾里德

2 个答案:

答案 0 :(得分:3)

此处无需使用loop

  1. 使用ddply / transform按年分组并获取data.frame
  2. 和cumsum计算累积降水量
  3. rev前进
  4. 你只需要改变5Jan 1Aug(第213天):

    library(plyr)
    ddply(dat,.(Year),transform, 
         TotPrecp= ifelse(DayOfYear > 5, NA,rev(cumsum(Precip))))
    

    这里的结果是:

      Site   Date Year DayOfYear DayofRun AveTemp MaxTemp MinTemp Precip TotPre TotPrecp
    1 EelRiver 1/1/02 2002         1        1    53.6      57      51   1.01     NA     5.10
    2 EelRiver 1/2/02 2002         2        2    52.5      64      43   1.30     NA     3.40
    3 EelRiver 1/3/02 2002         3        3    46.6      60      42   0.56     NA     2.87
    4 EelRiver 1/4/02 2002         4        4    45.7      57      41   0.00     NA     2.87
    5 EelRiver 1/5/02 2002         5        5    51.0      57      46   0.53     NA     2.31
    6 EelRiver 1/6/02 2002         6        6    57.9      60      55   1.70     NA       NA
    

    要回答关于循环的问题主要是因为副作用而很危险:

    for (i in 1:10) x <- 2             ## create a global variable x
    lapply (1:10, function(z) x <- 2)  ## SAFE don't create a gloable variable x
    

答案 1 :(得分:1)

未检查您的代码,但应该是for (i in 1:nrow(eelriverdata)) {而不是for (i in nrow(eelriverdata)) {

以下是我的版本,你只用年份而不是所有行循环。

我对某些问题不清楚,但尝试这种方法

试试这个:

set.seed(5)
tempdf=data.frame(year=rep(2002:2006, each=365), dayofyear=rep(1:365, times=5), prec=runif(365*5), totpre=0)

years=unique(tempdf$year)
for (i in 1:length(years)){
totpreindex<-which(tempdf[,"year"]==years[i] & tempdf[,"dayofyear"]==213)
totpre<-sum(tempdf[tempdf$year==years[i] & tempdf$dayofyear>0  & tempdf$dayofyear<213,"prec"])
tempdf[totpreindex,"totpre"]<-totpre
}

输出:

> tempdf[tempdf$totpre>0,]
     year dayofyear      prec   totpre
213  2002       213 0.4094868 108.9317
578  2003       213 0.2037912 109.2401
943  2004       213 0.3949180 112.0684
1308 2005       213 0.6600369 107.0455
1673 2006       213 0.5524957 102.6835