Jobbo90 Jobbo90 - 23 days ago 7
R Question

as.Date function gives different result in a for loop

Slight problem where my as.Date function gives a different result when I put it in a for loop. I'm looking in a folder with subfolders (per date) that contain images. I build date_list to organize all the dates (for plotting options in a later stage). The Julian Day starts from the first of January of the year, so because I have 4 years of date, the year must be flexible.

# Set up list with 4 columns and counter Q. jan is used to set all dates to the first of january
date_list <- outer(1:52, 1:4)
q = 1
jan <- "-01-01"

for (scene in folders){
year <- as.numeric(substr(scene, start=10, stop=13))
day <- as.numeric(substr(scene, start=14, stop=16))
datum <- paste(year, day, sep='_')
date_list[q, 1] <- datum
date_list[q, 2] <- year
date_list[q, 3] <- day
date_list[q, 4] <- as.Date(day, origin = as.Date(paste(year,jan, sep="")))
q = q+1
}


Output final row:

[52,] "2016_267" "2016" "267" "17068"


What am i missing in date_list[q, 4] that doesn't transfer my integer to a date?
running the following code does work, but due to the large amount of scenes and folders I like to automate this:

as.Date(day, origin = as.Date(paste(year,jan, sep="")))


Thank you for your time!

Answer

Well, I assume this would answer your first question:

date_list[q, 4] <- as.character(as.Date(datum,format="%Y_%j"))

as.Date accept a format argument, (the %Y and %j are documented in strptime), the %jis the julian day, this is a little easier to read than using origin and multiple paste calls.

Your problem is actually linked to what a Date object is:

> dput(as.Date("2016-01-10"))
structure(16810, class = "Date")

When entered into a matrix (your date_list) it is coerced to character w without special treatment before like this:

> d<-as.Date("2016-01-10")
> class(d)<-"character"
> d
[1] "16810"

Hence you get only the number of days since 1970-01-01. When you ask for the date as character representation with as.character, it gives the correct value because the Date class as a as.character method which first compute the date in human format before returning a character value.


Now if I understood well your problem I would go this way:

First create a function to work on one string:

name_to_list <- function(name) {
  dpart <- substr(name, start=10, stop=16)
  date <- as.POSIXlt(dpart, format="%Y%j")
  c("datum"=paste(date$year+1900,date$yday,sep="_"), "year"=date$year+1900, "julian_day"=date$yday, "date"=as.character(date) )
}

this function just get your substring, and then convert it to POSIXlt class, which give us julian day, year and date in one pass. as the year is stored as integer since 1900 (could be negative), we have to add 1900 when storing the year in the fields.

Then if your folders variable is a vector of string:

lapply(folders,name_to_list)

wich for folders=c("LC81730382016267LGN00","LC81730382016287LGN00","LC81730382016167LGN00") gives:

[[1]]
       datum         year   julian_day         date 
  "2016_266"       "2016"        "266" "2016-09-23" 

[[2]]
       datum         year   julian_day         date 
  "2016_286"       "2016"        "286" "2016-10-13" 

[[3]]
       datum         year   julian_day         date 
  "2016_166"       "2016"        "166" "2016-06-15"