1

I am trying to calculate the annual total of monthly product(binary files) https://echange-fichiers.inra.fr/get?k=Jr3tvgeKnWUiC1B0MMY. So I have 12 files and I have to calculate the total sum. The code given below worked fine but what I need is to multiply each file by the number of days which correspond to that month in that year then calculate the total sum. For my case, those data are for the year 2000 (a leap year), so I want to multiply the results for file number 1 by 31 and file number 2 by 29 and so on....

files<- list.files("C:\\jung file_2000_img", "*.img", full.names = TRUE)
x<- do.call(rbind,(lapply(files, readBin  , double() , size = 4 , n=360 * 720 , signed =TRUE)))
results <- colSums(x)
fileName <- sprintf("C:\\annual_ET2000_without999_1.img")
writeBin(as.double(results), fileName, size = 4)

From Jame's answer, this will calculate the number of days:

numDays <- function(month,year){
    as.numeric(strftime(as.Date(paste(year+month%/%12,month%%12+1,"01",sep="-"))-1,"%d"))
}

So now how to apply that to my code above? By that I mean that I want to take the result for each file and multiply it by the number of days like:

file1*numDays(1,2000)+file2*numDays(2,2000)+file3*numDays(3,2000)
   .............file12*numDays(12,2000) 
sacvf
  • 2,463
  • 5
  • 36
  • 54

3 Answers3

4

You can get the last day of the month by moving back one day from the first of the next month. So, try this:

numDays <- function(month,year){
  as.numeric(strftime(as.Date(paste(year+month%/%12,month%%12+1,"01",sep="-"))-1,"%d"))
}

Testing:

numDays(2,2012)
 [1] 29
numDays(2,2011)
 [1] 28
numDays(1,2011)
 [1] 31
numDays(12,2011)
 [1] 31
# vector of all month days in year 2000
sapply(1:12,numDays,2000)
 [1] 31 29 31 30 31 30 31 31 30 31 30 31
James
  • 65,548
  • 14
  • 155
  • 193
  • @WafaAlyaari I've added an example to get all month days in a particular year as a vector. Is `x` a matrix? If so, you just need to multiply by this. – James Oct 19 '12 at 15:50
  • yes it is a matrix. you mean I do this x*sapply(1:12,numDays,2000) then results <- colSums(x) – sacvf Oct 19 '12 at 15:54
4

I recommend you use the package lubridate, which has many useful functions for these type of things. For example:

> lubridate::days_in_month(as.Date("2000-02-01"))
Feb 
 29 
Alex
  • 15,186
  • 15
  • 73
  • 127
1

@James gave you a function for finding the number of days in a month (which you incorporated into your question). The next step is to weight the monthly values by the number of days. The problem is that you have put all the months together and there is no way to tell which is which thereafter. So don't combine them that much:

files<- list.files("C:\\jung file_2000_img", "*.img", full.names = TRUE)
x<- lapply(files, readBin  , double() , size = 4 , n=360 * 720 , signed =TRUE)
results <- sapply(x, colSums)
ann.results <- sum(sapply(1:12, function(m) {results[[m]] * numDays(m, 2000)}))

This makes a huge assumption: that files[[1]] corresponds to January, files[[12]] corresponds to December, and all between match as well.

What this does is make a list of data frames, one for each month. Then it uses colSums across the list to make a vector with the total for each month (same order as files). Finally, the months are iterated over to multiple the corresponding results values with the number of days (again, assuming that is the right corresponding month).

Community
  • 1
  • 1
Brian Diggs
  • 57,757
  • 13
  • 166
  • 188
  • I got these errors :> results <- sapply(x, colSums) Error in FUN(X[[1L]], ...) : 'x' must be an array of at least two dimensions > ann.results <- sum(sapply(1:12, function(m) {results[[m]] * numDays(m, 2000)})) Error in results[[m]] : subscript out of bounds – sacvf Oct 21 '12 at 08:27
  • I had to guess at the structure of your data, and I didn't test my answer (since the example wasn't reproducible without the files). If you could give (part of) `x` in a reproducible way, then we could possible give you working code. See http://stackoverflow.com/q/5963269/892313 – Brian Diggs Oct 22 '12 at 15:34