How to display real dates in a loop in r - r

When I iterate over dates in a loop, R prints out the numeric coding of the dates.
For example:
dates <- as.Date(c("1939-06-10", "1932-02-22", "1980-03-13", "1987-03-17",
"1988-04-14", "1979-08-28", "1992-07-16", "1989-12-11"), tryFormats = c("%Y-%m-%d"))
for(d in dates){
print(d)
}
The output is as follows:
[1] -11163
[1] -13828
[1] 3724
[1] 6284
[1] 6678
[1] 3526
[1] 8232
[1] 7284
How do I get R to print out the actual dates?
So the output reads:
[1] "1939-06-10"
[1] "1932-02-22"
[1] "1980-03-13"
[1] "1987-03-17"
[1] "1988-04-14"
[1] "1979-08-28"
[1] "1992-07-16"
[1] "1989-12-11"
Thank you!

When you use dates as seq in a for loop in R, it loses its attributes.
You can use as.vector to strip attributes and see for yourself (or dput to see under the hood on the full object):
as.vector(dates)
# [1] -11163 -13828 3724 6284 6678 3526 8232 7284
dput(dates)
# structure(c(-11163, -13828, 3724, 6284, 6678, 3526, 8232, 7284), class = "Date")
In R, Date objects are just numeric vectors with class Date (class is an attribute).
Hence you're seeing numbers (FWIW, these numbers count days since 1970-01-01).
To restore the Date attribute, you can use the .Date function:
for (d in dates) print(.Date(d))
# [1] "1939-06-10"
# [1] "1932-02-22"
# [1] "1980-03-13"
# [1] "1987-03-17"
# [1] "1988-04-14"
# [1] "1979-08-28"
# [1] "1992-07-16"
# [1] "1989-12-11"
This is equivalent to as.Date(d, origin = '1970-01-01'), the numeric method for as.Date.
Funnily enough, *apply functions don't strip attributes:
invisible(lapply(dates, print))
# [1] "1939-06-10"
# [1] "1932-02-22"
# [1] "1980-03-13"
# [1] "1987-03-17"
# [1] "1988-04-14"
# [1] "1979-08-28"
# [1] "1992-07-16"
# [1] "1989-12-11"

There are multiple way you can handle this :
Loop over index of dates :
for(d in seq_along(dates)){
print(dates[d])
}
#[1] "1939-06-10"
#[1] "1932-02-22"
#[1] "1980-03-13"
#[1] "1987-03-17"
#[1] "1988-04-14"
#[1] "1979-08-28"
#[1] "1992-07-16"
#[1] "1989-12-11"
Or convert date to list and then print directly.
for(d in as.list(dates)) {
print(d)
}

Related

Print a date range in a loop with correctly formatted dates [duplicate]

This question already has answers here:
Looping over a Date or POSIXct object results in a numeric iterator
(7 answers)
How to iterate over list of Dates without coercion to numeric?
(1 answer)
Closed 1 year ago.
Typing this into the console gives:
seq(as.Date('2020-04-02'), as.Date('2020-04-30'), by = 'day')
[1] "2020-04-02" "2020-04-03" "2020-04-04" "2020-04-05" "2020-04-06" "2020-04-07" "2020-04-08" "2020-04-09" "2020-04-10" "2020-04-11" "2020-04-12"
[12] "2020-04-13" "2020-04-14" "2020-04-15" "2020-04-16" "2020-04-17" "2020-04-18" "2020-04-19" "2020-04-20" "2020-04-21" "2020-04-22" "2020-04-23"
[23] "2020-04-24" "2020-04-25" "2020-04-26" "2020-04-27" "2020-04-28" "2020-04-29" "2020-04-30"
My loop:
for(i in seq(as.Date('2020-04-02'), as.Date('2020-04-30'), by = 'day')) {print(i)}
Gives:
[1] 18354
[1] 18355
[1] 18356
[1] 18357
[1] 18358
[1] 18359
[1] 18360
[1] 18361
[1] 18362
[1] 18363
[1] 18364
[1] 18365
[1] 18366
[1] 18367
[1] 18368
[1] 18369
[1] 18370
[1] 18371
[1] 18372
[1] 18373
[1] 18374
[1] 18375
[1] 18376
[1] 18377
[1] 18378
[1] 18379
[1] 18380
[1] 18381
[1] 18382
Expected actual dates.
Tried:
print(as.Date(i))
But this gives:
Error in as.Date.numeric(i) : 'origin' must be supplied
How can I print my date range via a loop?
Try:
for (i in as.list(seq(as.Date('2020-04-02'), as.Date('2020-04-30'), by = 'day'))) {
print(i)
}
I don't know why this is necessary, but if you run
for (i in Sys.Date()) {browser();print(i);}
# Called from: top level
# Browse[1]>
debug at #1: print(i)
# Browse[1]>
i
# [1] 18709
you'll see that i is being converted to numeric in the for (.) portion. The as.list helps preserve that class.
Another way is to supply the origin argument to as.Date:
for(i in seq(as.Date('2020-04-02'), as.Date('2020-04-30'), by = 'day')){
print(as.Date(i, origin="1970-01-01"))}
When R transforms a date into a numeric, it returns the number of days after 197-01-01. Other softwares use different origins.

Saving dates in a matrix ("origin must be supplied") with r

I am writing my bachelor thesis and I have not much experience with r so far.
My problem is that my dates which I made with this commands :
t<-strptime(x, "%d.%m.%Y %H.%M")
don't work anymore when I save them in a matrix with the other information on those specific dates.
I am a bit confused because it works just fine when I don't put them in a matrix like this t[1:10]
But that happens as soon as I try to save them in a matrix
matrix1<-matrix(c(t,v2,v3,v4),nrow=length(v2))
Fehler in as.POSIXct.numeric(X[[i]], ...) : 'origin' muss angegeben werden
It's German but it means origin must be supplied.
Any ideas what I have to do to fix it? I am a bit frustrated :)
Roland is right. You can't have Posixlt objects in a matrix. What you can do is save those dates as numeric timestamps in the matrix and convert them back to dates while accessing
Converting to numeric timestamp:
>date<- as.numeric(as.POSIXct("2014-02-16 2:13:46 UTC",origin="01-01-1970"))
>date
[1] 1392545626
Then save those timestamps in a matrix as you do and to convert it back to date, use the above command again without converting it into a numeric.
t (terrible name by the way, easily confused with the t function) is a POSIXlt object, which internally is a list. First you should check, what c(t,v2,v3,v4) returns (I don't know how v2 etc are defined).
Then we can look into the documentation in help("matrix"):
data
an optional data vector (including a list or expression vector). Non-atomic classed R objects are coerced by as.vector and all attributes discarded.
The important bit is "all attributes discarded". This is what you get if you discard the attributes (which include the class attribute) of a POSIXlt object:
x <- strptime(c("2016-05-09 12:00:00", "2016-05-09 13:00:00"), format = "%Y-%m-%d %H:%M:%S")
attributes(x) <- NULL
print(x)
# [[1]]
# [1] 0 0
#
# [[2]]
# [1] 0 0
#
# [[3]]
# [1] 12 13
#
# [[4]]
# [1] 9 9
#
# [[5]]
# [1] 4 4
#
# [[6]]
# [1] 116 116
#
# [[7]]
# [1] 1 1
#
# [[8]]
# [1] 129 129
#
# [[9]]
# [1] 1 1
#
# [[10]]
# [1] "CEST" "CEST"
#
# [[11]]
# [1] NA NA
A matrix can't contain POSIXlt objects (or any objects, i.e., anything with an explicit class).

Looping over dates with R

I need to write some code in R that builds a string by looping over dates and I cant' seem to find an example of this in my books or by Googling. Basically:
for theDate = 1Jan14 to 31Dec14{
"http://website.com/api/" + theDate
}
I thought about creating an input file that held the dates, but that seems inelegant.Does anybody know of a better solution?
This doesn't consume that much memory and doesn't need the julian function:
start <- as.Date("01-08-14",format="%d-%m-%y")
end <- as.Date("08-09-14",format="%d-%m-%y")
theDate <- start
while (theDate <= end)
{
print(paste0("http://website.com/api/",format(theDate,"%d%b%y")))
theDate <- theDate + 1
}
.
[1] "http://website.com/api/01Aug14"
[1] "http://website.com/api/02Aug14"
[1] "http://website.com/api/03Aug14"
[1] "http://website.com/api/04Aug14"
[1] "http://website.com/api/05Aug14"
[1] "http://website.com/api/06Aug14"
[1] "http://website.com/api/07Aug14"
[1] "http://website.com/api/08Aug14"
[1] "http://website.com/api/09Aug14"
[1] "http://website.com/api/10Aug14"
[1] "http://website.com/api/11Aug14"
[1] "http://website.com/api/12Aug14"
[1] "http://website.com/api/13Aug14"
[1] "http://website.com/api/14Aug14"
[1] "http://website.com/api/15Aug14"
[1] "http://website.com/api/16Aug14"
[1] "http://website.com/api/17Aug14"
[1] "http://website.com/api/18Aug14"
[1] "http://website.com/api/19Aug14"
[1] "http://website.com/api/20Aug14"
[1] "http://website.com/api/21Aug14"
[1] "http://website.com/api/22Aug14"
[1] "http://website.com/api/23Aug14"
[1] "http://website.com/api/24Aug14"
[1] "http://website.com/api/25Aug14"
[1] "http://website.com/api/26Aug14"
[1] "http://website.com/api/27Aug14"
[1] "http://website.com/api/28Aug14"
[1] "http://website.com/api/29Aug14"
[1] "http://website.com/api/30Aug14"
[1] "http://website.com/api/31Aug14"
[1] "http://website.com/api/01Sep14"
[1] "http://website.com/api/02Sep14"
[1] "http://website.com/api/03Sep14"
[1] "http://website.com/api/04Sep14"
[1] "http://website.com/api/05Sep14"
[1] "http://website.com/api/06Sep14"
[1] "http://website.com/api/07Sep14"
[1] "http://website.com/api/08Sep14"
>
You can use
> dates <- seq(as.Date("2014-01-01"), as.Date("2014-12-31"), by=1)
to generate a vector of consecutive days. What you want to do with this is not entirely clear from your pseudo-code, but you can iterate directly over the vector (which is generally not what you want in R)
> for (d in dates) {
# Code goes here.
}
The comment-solution by #Roland will give you a vector of the form:
> paste0("http://website.com/api/", dates)
[1] "http://website.com/api/2014-01-01" "http://website.com/api/2014-01-02"
[3] "http://website.com/api/2014-01-03" "http://website.com/api/2014-01-04"
[5] "http://website.com/api/2014-01-05" "http://website.com/api/2014-01-06"
...
Of course after I ask the question I happen to find this.
days <- seq(from=as.Date('2011-02-01'), to=as.Date("2011-03-02"),by='days' )
for ( i in seq_along(days) )
{
print(paste(days[i],"T12:00:00", sep=""))
}
You could translate your date into julian days and then write a loop based on the julian days.
To convert to julian days you can use the code described here
And then you could write code using the the julian days like:
tmp <- as.POSIXlt("1Jan14", format = "%d%b%y")
strdate <- julian(tmp)
tmp <- as.POSIXlt("31Dec14", format = "%d%b%y")
enddate <- julian(tmp)
for (theDate in strdate:enddate){
paste ("http://website.com/api/", toString(theDate), sep = "")
}
you have to figure out how to convert back. I am not to sure about the julian function. maybe you should also have a look into "yday" of lubridate package.

Populating a list with lists (replicate, lapply)

How should I generate a list of lists of known size?
Currently I do it like that.
create_scout_bees <- function(search_space, num_scouts){
gen_bee <- function(unused, sear_spac){
create_random_bee(sear_spac)
}
bees <- lapply(1:num_scouts, gen_bee, search_space)
#bees <- replicate(num_scouts, create_random_bee(search_space))
cat('\nclass of bees is:',class(bees),'\n')
bees
}
where create_random_bee(sear_spac) returns return(list(vector=random_vector(search_space))). This seems to be too complicated. I found the replicate function (see comment in code). But it does not return the same thing. To be honest I'm not entirely sure what it returns.
The lapply option seems returns a list of lists
[[1]]
[[1]]$vector
[1] -3.772477 -4.178604
[[2]]
[[2]]$vector
[1] -1.237291 -2.430769
[[3]]
[[3]]$vector
[1] -2.211511 -1.352074
[[4]]
[[4]]$vector
[1] 4.102391 -1.437620
[[5]]
[[5]]$vector
[1] -0.1355444 -2.0270074
The replicate version returns a list
$vector
[1] 3.780779 3.588892
$vector
[1] -4.290371 4.098709
$vector
[1] 1.051525 -3.374406
$vector
[1] -0.4593861 -4.8412850
$vector
[1] 2.164383 -4.903347
I can index both returned values. But the second option seems to be just a list with 5 elements of type vector with the same key. When accessing by key it returns the first element.
How do you generate a list of lists of known size?
You can try
replicate(5, list(vector=rnorm(2)), simplify=FALSE)
# [[1]]
#[[1]]$vector
#[1] -1.5239454 -0.1326934
#[[2]]
#[[2]]$vector
#[1] -1.4369404 0.3701259
#[[3]]
#[[3]]$vector
#[1] 0.3251298 -1.4289498
#[[4]]
#[[4]]$vector
#[1] 0.8346002 -0.2974959
#[[5]]
#[[5]]$vector
#[1] 0.4581858 -0.8066517

Get the second value in the row if the dates match in R

I am in the trouble of getting the values which have the same dates from two different data sources in R. The code is
#Monthly data
month_data <- c(580.11, 618.25, 641.24, 604.85, 580.86, 580.07, 632.97,
685.09, 754.50, 680.30, 698.37, 707.38, 480.11, 528.25,
541.24, 614.85, 680.86)
month_dates <- seq(as.Date("2001/06/01"), by = "1 months", length = 17)
month_data <- data.frame(month_dates, month_data)
#the dates_for_match is a list:
dates_for_match<-list(c( "2001-08-01","2001-09-01", "2001-10-01"),c("2001-11-01","2001-12-01","2002-01-01"),c("2002-02-01","2002-03-01","2002-04-01"),c("2002-05-01","2002-06-01","2002-07-01"),c( "2002-08-01","2002-09-01", "2002-10-01"))
Example:
> dates_for_match
[[1]]
[1] "2001-08-01" "2001-09-01" "2001-10-01"
[[2]]
[1] "2001-11-01" "2001-12-01" "2002-01-01"
[[3]]
[1] "2002-02-01" "2002-03-01" "2002-04-01"
[[4]]
[1] "2002-05-01" "2002-06-01" "2002-07-01"
[[5]]
[1] "2002-08-01" "2002-09-01" "2002-10-01"
I want to use the dates_for_match list to get the values from month_data that have the same dates.
You need %in%...
month_data[ month_dates %in% unlist( dates_for_match ) , 2 ]

Resources