R Converting Datetime to an actual string - r

I am trying to convert a date time to an actual string. But when I use as.character(x) then it returns a value that I can't convert to a date or time.
for instance:
When I extract the data from a particular cell in the dataframe df it returns:
> df[1,6]
# A tibble: 1 x 1
`PLS FFM`
<dttm>
1 2019-12-14 06:47:00
When I try to convert it to a string it returns:
> (as.character(df[1,6]))
[1] "1576306020"
But when I try to convert the string or the datetime () to a date format it returns:
> as.Date(as.character(df[1,6]))
Error in charToDate(x) :
character string is not in a standard unambiguous format
I all ready searched on the internet for hours trying to find a solution, but it's seems that I either doings something wrong or I am honestly really stupid.
Can somebody help me out!?
Thanks,
JOP
Answer thanks to Ronak Shah!
After Ronak Suggested that I should convert the whole vector with format I was able to convert the formatted vector to a Date + time that I can use in my script where I make a lot of calculations with the time. I Used:
df$'PLS FFM' <- format(df$'PLS FFM')
df$'PLS FFM' <- as.POSIXCT(df$'PLS FFM')
Thanks to Ronak

Since df[1,6] is still a tibble using as.character doesn't work on it. You need to pass a vector to as.character which can be done with
as.character(df$`PLS FFM`)
#OR
#as.character(df[["PLS FFM"]])
We can also use format
format(df$`PLS FFM`)
If you need a specific value from the dataframe, use
as.character(df$`PLS FFM`[1])

Related

Converting character variable in date format

I'd like to convert my variable "birthdate" from a character class to dates. They're actually written like that "dd/mm/yyyy". I tried to use the function as.Date but I obtained something wrong :
x$age <- as.Date(x$birhtdate)
R doesn't read the character string correctly. For example 21/12/1948 becomes 0021/12/19
I am a bit lost, I also tried to use the function format but without success.
Thank for your help !
You can use the R package lubridate to explicitly use specific ordering of day and month:
x <- data.frame(birhtdate = "21/12/1948")
x$birhtdate <- lubridate::parse_date_time(x$birhtdate, orders = "dmy")
x
#> birhtdate
#> 1 1948-12-21
Created on 2023-01-04 by the reprex package (v2.0.1)
base R answer:
Yes, you need to provide R with the format, there are so much different possibilities like '-' or a space or different order mm/dd/yyyy
So:
as.Date('21/12/1948', format = '%d/%m/%Y')
will work.
Output:
[1] "1948-12-21"

Difftime shows 0 for every ride_length

Im new to coding in R and cant seem to figure out what the problem here is, the difftime() function always shows the results as 0 when I try to make a new column.
all_trips$ride_length <- difftime(all_trips$ended_at,all_trips$started_at)
Glimpse
$ started_at <chr> "2019-04-01 00:02:22",
$ ended_at <chr> "2019-04-01 00:09:48",
Welcome to SO! In general please post a minimal reproducible example of the relevant parts of your dataset using dput() or similar.
The <chr> in your output means that your columns are a character vector rather than date time.
As pointed out in the comments by jay.sf, difftime() can parse character vectors in some formats, and it should be able to parse the single example given in your post.
Nevertheless, in general it is better to store datetimes as one of the built-in datetime classes, i.e. either POSIXct or POSIXlt, rather than to rely on implicit coercion. To convert them:
all_trips$started_at <- as.POSIXct(all_trips$started_at)
all_trips$ended_at <- as.POSIXct(all_trips$ended_at)
# Calculate diff time
all_trips$ride_length <- difftime(
all_trips$ended_at,
all_trips$started_at,
units = "secs"
)
You will get an error if the conversion does not work:
as.POSIXct(c("2019-04-01 00:02:22", "not a valid date time"))
Error in as.POSIXlt.character(x, tz, ...) :
character string is not in a standard unambiguous format
This is the same error you will get if you try to use difftime() with a character vector that is not unambiguously a datetime.
This post is a useful discussion of R's internal handling of date/time classes.

regex single digit

I have a question which I think is solved by regex use in R.
I have a set of dates (as chr) which I would like in a different format (as chr).
I have tried to fool around with the below examples where the first (new_dates) gives the right format for months 1-9 and wrong for 10-12 and (new_dates2) gives the right format for 10-12 but nothing for 1-9.
I see that the code in the first case matches a single digit twice for 10-12, but don't really know how to tell it to match only single digit.
The final vector of correct dates shows the result I would like.
dates <- c("1/2016", "2/2016", "3/2016", "4/2016", "5/2016", "6/2016", "7/2016", "8/2016", "9/2016", "10/2016", "11/2016", "12/2016", "1/2017")
new_dates <- sub("(\\d)[:/:](\\d{4})","\\2M0\\1", dates)
new_dates2 <- sub("(\\d{2})[:/:](\\d{4})","\\2M\\1", dates)
correctdates <- c("2016M01", "2016M02", "2016M03", "2016M04", "2016M05", "2016M06", "2016M07", "2016M08", "2016M09", "2016M10", "2016M11", "2016M12", "2017M1")
Here's a base R method that will return the desired format:
format(as.Date(paste0("1/",dates), "%d/%m/%Y"), "%YM%m")
[1] "2016M01" "2016M02" "2016M03" "2016M04" "2016M05" "2016M06" "2016M07" "2016M08" "2016M09"
[10] "2016M10" "2016M11" "2016M12" "2017M01"
The idea is to first convert to a Date object and then use the format function to create the desired character representation. I pasted on 1/ so that a day is present in each element.
As #a p o m said it might be better to look for another solution if you are manipulating dates but if you want to stick with regular expressions you can try this one.
([02-9]|1[0-2]?)[:\/](\d{4}) example
new_dates <- sub("(\\d{1,2})\\/(\\d{4})","\\2M0\\1", dates)
It's fine.

How to lag dates in form of strings in R

The following vector of Dates is given in form of a string sequence:
d <- c("01/09/1991","01/10/1991","01/11/1991","01/12/1991")
I would like to exemplary lag this vector by 1 month, that means to produce the following structure:
d <- c("01/08/1991","01/09/1991","01/10/1991","01/11/1991")
My data is much larger and I must impose higher lags as well, but this seems to be the basis I need to know.
By doing this, I would like to have the same format in the end again:("%d/%m/%Y). How can this be done in R? I found a couple of packages (e.g. lubridate), but I always have to convert between formats (strings, dates and more) so it's a bit messy and seems prone to mistake.
edit: some more info on why I want to do this: I am using this vector as rownames of a matrix, so I would prefer a solution where the final outcome is a string vector again.
This does not use any packages. We convert to "POSIXlt" class, subtract one from the month component and convert back:
fmt <- "%d/%m/%Y"
lt <- as.POSIXlt(d, format = fmt)
lt$mon <- lt$mon - 1
format(lt, format = fmt)
## [1] "01/08/1991" "01/09/1991" "01/10/1991" "01/11/1991"
My solution uses lubridatebut it does return what you want in the specified format:
require(lubridate)
d <- c("01/09/1991","01/10/1991","01/11/1991","01/12/1991")
format(as.Date(d,format="%d/%m/%Y")-months(1),'%d/%m/%Y')
[1] "01/08/1991" "01/09/1991" "01/10/1991" "01/11/1991"
You can then change the lag and (if you want) the output (which is this part : '%d/%m/%Y') by specifying what you want.

convert factor to date with empty cells

I have a factor vector x looking like this:
""
"1992-02-13"
"2011-03-10"
""
"1998-11-30"
Can I convert this vector to a date vector (using as.Date())?
Trying the obvious way gives me:
> x <- as.Date(x)
Error in charToDate(x) :
character string is not in a standard unambiguous format
At the moment I solve this problem like this:
> levels(x)[1] <- NA
> x <- as.Date(x)
But this doesn't look too elegant...
Thank you in advance!
You simply need to tell as.Date what format to expect in your character vector:
xd <- as.Date(x, format="%Y-%m-%d")
xd
[1] NA "1992-02-13" "2011-03-10" NA "1998-11-30"
To illustrate that these are indeed dates:
xd[3] - xd[2]
Time difference of 6965 days
PS. This conversion using as.Date works regardless of whether your data is a character vector or a factor.
When you pull in the data with read.csv, or others, you can set
read.csv(...,na.strings=c(""))
to avoid having to deal with this entirely.
I usually convert factors to a POSIX* type class using the function strptime. First argument is your vector and the second argument is the "pattern" by which the date/time is constructed (a % sign + a specific letter). You basically tell R that first you have a year, then you have a -, then a month and so on. See ?strptime for a full list of conversion specifications.
x <- factor(c("1992-02-13", "2011-03-10", "1998-11-30"))
(x.date <- strptime(x, format = "%Y-%m-%d"))
[1] "1992-02-13" "2011-03-10" "1998-11-30"
class(x.date)
[1] "POSIXlt" "POSIXt"
The same principle holds for as.Date. You tell R to "make this a date/time object and here are the instructions on how to make it".
(as.Date(x, "%Y-%m-%d"))
[1] "1992-02-13" "2011-03-10" "1998-11-30"

Resources