-1

I have a data frame with empty columns. I want to fill one row of that data frame with dates.

x <- data.frame(a = 1:2, b = rep(NA, 2), c = rep(NA, 2))
mydates <- as.Date(c("2016-01-31", "2016-02-29"))
x[1, c("b", "c")] <- mydates
x
str(x)

My dates appear in the first row as numeric values and columns b and c are numeric now. Clearly not what I want.

How about this:

x <- data.frame(a = 1:2, b = rep(NA, 2), c = rep(NA, 2))
for (v in c("b", "c")) x[[v]] <- as.Date(x[[v]])
x
str(x)
x[1, c("b", "c")] <- mydates

Although I declared my variables as dates, it's not working.

What works is:

x <- data.frame(a = 1:2, b = rep(NA, 2), c = rep(NA, 2))
x
x[1, c("b", "c")] <- mydates
x
for (v in c("b", "c")) x[[v]] <- as.Date(x[[v]])
x
str(x)

Could anyone please explain what exactly is going on and why the 3rd block of code works but the second doesn't? In fact, I am not even sure why the first block of code isn't working...

Thank you very much!

user3245256
  • 1,842
  • 4
  • 24
  • 51

1 Answers1

1

As stated in comments, there is a need to set the class of the columns to Date. But it's also helpful to pass these values as a named list.

> x <- data.frame(a = 1:2, b = as.Date(rep(NA, 2)), c = as.Date(rep(NA, 2)))
> x
  a    b    c
1 1 <NA> <NA>
2 2 <NA> <NA>
> x[1, c("b", "c")] <- list( b= as.Date(c("2016-01-31"), c=as.Date("2016-02-29")) )
> x
  a          b          c
1 1 2016-01-31 2016-01-31
2 2       <NA>       <NA>
> str(x)
'data.frame':   2 obs. of  3 variables:
 $ a: int  1 2
 $ b: Date, format: "2016-01-31" NA
 $ c: Date, format: "2016-01-31" NA

Here's a more complicated test of the method I'm suggesting (since I got tired of waiting for you to post a more complicated example in code):

x <- data.frame(a = 1:3, b = as.Date(rep(NA, 3)), c = as.Date(rep(NA, 3)))
x
#----------
  a    b    c
1 1 <NA> <NA>
2 2 <NA> <NA>
3 3 <NA> <NA>
#---
x[1:2, c("b", "c")] <- list( b= as.Date(c("2016-01-31", "2020-02-09"), c=as.Date("2016-02-29", "2027-08-22")) )
x
#####
  a          b          c
1 1 2016-01-31 2016-01-31
2 2 2020-02-09 2020-02-09
3 3       <NA>       <NA>

This is reminding me of an earlier answer to a somewhat different question that I posted which was inspired by a comment from Gabor Grothendeick (which I will now attempt to track down.) Found it; The last of my examples shows how to use logical tests as the "indexing" for assignments to "blocks" of items in a dataframe: R self reference

IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • Thank you and I apologize - I slightly updated my question. In real life, my dates are saved in a vector mydates. And your solution with the list - while it's very nice - is not working when I have a vector mydates. list(mydates) is not working. – user3245256 Jan 30 '19 at 23:22
  • You need to show with code what is "not working" Your update does not appear to do so. – IRTFM Jan 31 '19 at 01:26
  • My 3rd block of code is working. My question was rather - why doesn't the 2nd one work? – user3245256 Jan 31 '19 at 15:56
  • @user3245256 There isn't going to be a terribly satisfying explanation beyond "inserting a list rather than a vector avoids some coercion pathways in `[<-.data.frame`". The basic lesson is that you can't expect to do rowwise insertions on data frames with vectors and have things work the way you expect in all cases. – joran Jan 31 '19 at 16:16
  • @joran OK, I understand, however, I am still not having an example of a solution with a list that is using mydates. – user3245256 Jan 31 '19 at 19:26
  • @user3245256 The above answer is a solution using a list. The idea is that instead of creating `mydates` with `c()` you create it with `list()`. Or possibly convert it to a list via `as.list()`. – joran Jan 31 '19 at 19:32
  • @joran Thank you, as.list worked! So, the solution is: x <- data.frame(a = 1:3, b = as.Date(rep(NA, 3)), c = as.Date(rep(NA, 3))); mydates <- as.list(as.Date(c("2016-01-31", "2020-02-09"))); x[1:2, c("b", "c")] <- mydates – user3245256 Feb 01 '19 at 17:17
  • @joran Could you please amend your response using mydates (as in my previous comment) so that I could accept your answer? Thank you! – user3245256 Feb 01 '19 at 17:22
  • @user3245256 I would just accept this one, it is identical to what I suggested. – joran Feb 01 '19 at 17:27