1

There are 25 years worth of values, so 25 columns and 49,681 sites, so 49,681 rows. I am trying to create a matrix that is filled with the means of the NDVI values from each year and each site. So if you look at column 1, row 2 you will see the mean from site 2 (out of 49,681) in year 1. However, my for-loop isn't working. Does anyone know what i'm doing wrong. I am completely new to r. enter image description here

for(i in 1:49681){
  mean(as.numeric(veg.data[i,4:27]))     ##NDVI average for 1982 
  mean(as.numeric(veg.data[i,28:51]))    ##NDVI average for 1983 (site 2)
  mean(as.numeric(veg.data[i,51:75]))    ##NDVI average for 1984 (site 3)
  mean(as.numeric(veg.data[i,76:99]))    ##NDVI average for 1985 (site 4)
  mean(as.numeric(veg.data[i,100:123]))  ##NDVI average for 1986 (site 5)
  mean(as.numeric(veg.data[i,124:147]))  ##NDVI average for 1987 (site 6)
  mean(as.numeric(veg.data[i,148:171]))  ##NDVI average for 1988 (site 7)
  mean(as.numeric(veg.data[i,172:195]))  ##NDVI average for 1989 (site 8)
  mean(as.numeric(veg.data[i,196:219]))  ##NDVI average for 1990 (site 9)
  mean(as.numeric(veg.data[i,220:243]))  ##NDVI average for 1991 (site 10)
  mean(as.numeric(veg.data[i,244:267]))  ##NDVI average for 1992 (site 11)
  mean(as.numeric(veg.data[i,268:291]))  ##NDVI average for 1993 (site 12)
  mean(as.numeric(veg.data[i,292:315]))  ##NDVI average for 1994 (site 13)
  mean(as.numeric(veg.data[i,316:339]))  ##NDVI average for 1995 (site 14)
  mean(as.numeric(veg.data[i,340:363]))  ##NDVI average for 1996 (site 15)
  mean(as.numeric(veg.data[i,364:387]))  ##NDVI average for 1997 (site 16)
  mean(as.numeric(veg.data[i,388:411]))  ##NDVI average for 1998 (site 17)
  mean(as.numeric(veg.data[i,412:435]))  ##NDVI average for 1999 (site 18)
  mean(as.numeric(veg.data[i,436:459]))  ##NDVI average for 2000 (site 19)
  mean(as.numeric(veg.data[i,460:483]))  ##NDVI average for 2001 (site 20)
  mean(as.numeric(veg.data[i,484:507]))  ##NDVI average for 2002 (site 21)
  mean(as.numeric(veg.data[i,508:531]))  ##NDVI average for 2003 (site 22)
  mean(as.numeric(veg.data[i,532:555]))  ##NDVI average for 2004 (site 23)
  mean(as.numeric(veg.data[i,556:579]))  ##NDVI average for 2005 (site 24)
  mean(as.numeric(veg.data[i,580:603]))  ##NDVI average for 2006 (site 25)
}
  yearly.averages[i] <- matrix(c(rep(i,49681*25)),nrow= 49681 ,ncol= 25)
  head(yearly.averages) ##test to see if correct 
Shelby
  • 19
  • 3
  • 1
    If you type `mean(1:10)` in the console, you'll see the answer `5.5`, but it isn't stored anywhere. If you want to see it again later, you have to assign it, with `x <- mean(1:10)`, or something like that. The same is true inside the `for` loop. Inside a for loop, automatic printing is suppressed, so all your means aren't printed as you run the loop. But because you don't do any assignment with `<-` inside the for loop, none of the results are saved. – Gregor Thomas Dec 02 '19 at 01:46
  • To make your loop work, create a matrix full of `0`s or `NA`s *before* the loop, then have each line in the loop assign to the correct element... `yearly.averages[i, 1] <- mean(...)`, etc. – Gregor Thomas Dec 02 '19 at 01:47
  • However, a much nicer approach would be to convert your data from wide format to long format, at which point doing a grouped mean would be one or two lines of code. Basically, you would do [something like this grouped wide to long](https://stackoverflow.com/q/9684671/903061), then pick your favorite [mean by group R-FAQ](https://stackoverflow.com/q/11562656/903061) solution. If you post a bit of sample data, say `dput(droplevels(your_data[1:10, c(1:3, 4:6, 28:31)]))`, we can help you out with that. But it's hard to help more than these comments without sample data. – Gregor Thomas Dec 02 '19 at 01:50

2 Answers2

1

Taking account of Gregor's first two comments and R's vector nature, you might want to try something like

yearly.averages <- matrix(nrow=49681, ncol=25)
for (j in 1:25){
    yearly.averages[, j] <- rowMeans(matrix(as.numeric(
                            veg.data[, (1:24) + j*24 - 21]), ncol=24))
    }
head(yearly.averages)

though whether this works may depend on your actual data (is yearly.averagesa matrix or a dataframe?)

Henry
  • 6,704
  • 2
  • 23
  • 39
0
  • Assuming you are using data.frame for your data veg.data (numeric), maybe you can try the following code:
yearly.averages <- data.frame(Map(colMeans,split(data.frame(t(veg.data[-(1:3)])),rep(1:25,1,each = 24))))

If data in veg.data is character, you can replace veg.data[-(1:3)] by as.numeric(veg.data[-(1:3)])

  • if veg.data is a matrix and the desired output yearly.averages should be a matrix as well, then the above code should be correspondingly adapted to
yearly.averages <- sapply(split(data.frame(t(veg.data[,-(1:3)])),rep(1:25,1,each = 24)),colMeans)
ThomasIsCoding
  • 96,636
  • 9
  • 24
  • 81