0

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!

Jobbo90
  • 175
  • 1
  • 11
  • 1
    What is in `folders` ? I think there's probably a better way to achieve what you want. You should get rid of the `as.Date()` call in `origin` parameter, the `as.Date` function will convert the parameter to date as needed, or if specific, you should give an origin here too. – Tensibai Nov 16 '16 at 16:05
  • @Tensibai In folders is a bunch satellite images acquired on 1 day and then for 52 days. In the name of the images is the stored date: LC81730382016267LGN00. This example was captured at day 267 of 2016. The following: as.Date(day, origin = as.Date(paste(year,jan, sep=""))) Wil transfer it in 2016-09-24, which is what I want. But it doesn't succesfully store in the date_list – Jobbo90 Nov 17 '16 at 07:22
  • I mean a `dput folders` would help to help you :) – Tensibai Nov 17 '16 at 07:45

2 Answers2

0

Do you mean to output your day as 3 numbers? Should it not be 2 numbers?

day <- as.numeric(substr(scene, start=15, stop=16))

or

day <- as.numeric(substr(scene, start=14, stop=15))

That could at least be part of the issue. Providing an example of what typical values of "scene" are would be helpful here.

user3466328
  • 398
  • 1
  • 11
  • Julian days are range from values 1 - 365 so the day is in three numbers. So I'm not sure how that could be part of the problem. Scene is the name of the images in the folders, it is the itirator that I use. Like: 'LC81730382016267LGN00' Thanks for your time! – Jobbo90 Nov 17 '16 at 07:19
  • Ah its in Julian days, I see, my bad! – user3466328 Nov 17 '16 at 19:00
0

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" 
Tensibai
  • 15,557
  • 1
  • 37
  • 57
  • Hero of the day! Thank you! One remark on your first part of the answer: within a for loop (itirating through folders with images) this still doesn't work. Outside a loop it does. But your lapply function works great, thanks. – Jobbo90 Nov 17 '16 at 09:31
  • @Jobbo90 Indeed, I overlooked a part at first, I edited the answer for a more complete explanation and correct fix. – Tensibai Nov 17 '16 at 09:44