mantanam
mantanam

Reputation: 27

Passing Sequence of Dates to dataframe column

I am trying to pass a sequence of dates to a dataframe:

DF_1 <- as.data.frame(matrix(ncol=2))            
days <-seq(as.Date("2016-01-01"), as.Date(Sys.time(),"%Y-%m-%d"), by="days")
    
for (i in 1:length(days)) {
      print(days[i])
      DF_1[i,1] <- days[i]
    }

The result of print function is:

[1] "2021-06-23"
[1] "2021-06-24"
[1] "2021-06-25"
[1] "2021-06-26"
[1] "2021-06-27"
[1] "2021-06-28

" But the column 1 in DF1 is:

16801
16802
16803
16804
16805

Why the secuence of dates is changing in the dataframe?

Upvotes: 1

Views: 434

Answers (2)

AndrewGB
AndrewGB

Reputation: 16836

You can also use dplyr to add the dates to your initialized data frame.

library(dplyr)

# Set up your dataframe based on the length of days.
days <-seq(as.Date("2016-01-01"), as.Date(Sys.time(),"%Y-%m-%d"), by="days")
DF_1 <- as.data.frame(matrix(ncol=2, nrow = length(days)))

# Then, add the date data to the first column in the initialized dataframe.
DF_2 <- DF_1 %>%
  dplyr::mutate(V1 = days)

Another option is to use purrr to turn the date data into a tibble. You can rename the column and create a second column if needed.

library(purrr)
library(dplyr)

df <- days %>% 
  purrr::map_df(as_tibble) %>% 
  dplyr::rename(date = 1) %>% 
  dplyr::mutate(V2 = NA)

Upvotes: 2

akrun
akrun

Reputation: 886948

It is better to initialize the 'DF' as

DF_1 <- data.frame(days)
str(DF_1)
'data.frame':   2006 obs. of  1 variable:
 $ days: Date, format: "2016-01-01" "2016-01-02" "2016-01-03" "2016-01-04" ...

Or if we still want to use a for loop, initialize with Date class instead of logical (matrix creates the NA row which are logical)

DF_1 <- data.frame(col1 = as.Date(rep(NA, length(days))))

Now, if we do the loop

for (i in 1:length(days)) {
      print(days[i])
      DF_1[i,1] <- days[i]
    }

checking the class

str(DF_1)
'data.frame':   2006 obs. of  1 variable:
 $ col1: Date, format: "2016-01-01" "2016-01-02" "2016-01-03" "2016-01-04" ...

The issue is the coercion of Date to its integer storage values. We can find the behavior also when unlist

unlist(as.list(head(days)))
[1] 16801 16802 16803 16804 16805 16806

or with unclass

unclass(head(days))
[1] 16801 16802 16803 16804 16805 16806

which can be corrected with c in do.call if the input is a list

do.call(c, as.list(head(days)))
[1] "2016-01-01" "2016-01-02" "2016-01-03" "2016-01-04" "2016-01-05" "2016-01-06"

or convert the integer back to Date class afterwards by specifying the origin in as.Date

as.Date(unlist(as.list(head(days))), origin = '1970-01-01')
[1] "2016-01-01" "2016-01-02" "2016-01-03" "2016-01-04" "2016-01-05" "2016-01-06"

Upvotes: 2

Related Questions