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.
Related
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])
Sometimes I work with data like this:
sep-2018
From date like this:
Sys.Date()
[1] "2018-09-21"
To have this result, I generally use:
format(Sys.Date(),'%b-%Y')
But its class is not a date:
class(format(Sys.Date(),'%b-%Y'))
[1] "character"
Why it's not a date? Is it possible to have it with class() = date, and how?
Also an external library like zoo have the same thing.
library(zoo)
> class(format(as.yearmon(format(Sys.Date()), "%Y-%m-%d"), "%b.%Y"))
[1] "character"
Also using "%m.%Y" seems to generate the same thing, but it does not creates (for example) ordering issue.
The format command takes the date and outputs a printable string based on the format you provide. To quote the documentation:
An object of similar structure to x containing character representations of the
elements of the first argument x in a common format, and in the current
locale's encoding.
Also, a Date variable is stored as a numeric type internally (number of days since 1970-01-01)
dput(Sys.Date())
#structure(17795, class = "Date")
structure(0, class = "Date")
#[1] "1970-01-01"
So to pinpoint the date, you need day, month and year fields. If you don't have all three, it will probably return NA or an error. Similarly for time classes. If you don't have the data then you can just use some dummy values, and use format to print only the fields you want.
As Rohit says, format doesn't outputs a Date object, but a string in the format of your choice.
To get a Date object from a string like "sep-2018" you could use readr::parse_date().
(my_date <- readr::parse_date("sep-2018", format = '%b-%Y'))
#[1] "2018-09-01"
class(my_date)
#[1] "Date"
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.
When I read in a data file using R, a Date variable is a Factor.
For example, let epc hold the data set. Then if we look at the structure of the first date, we get
str(epc$Date[1])
Factor w/ 1 level "16/12/2006": 1
If you were to convert this to a character, as.character(epc$Date[1]), you'd get exactly the same thing: "16/12/2006"
No matter what I've tried, I can't convert this type of object into a valid date.
if the date is "16/12/2006" (which I'm assuming is Dec. 16th, 2006), then as.Date(epc_full$Date[1]) gives "0016-12-20" -- the full year is lost.
I've tried many different things, e.g., first converting the date into a character, trying different versions of as.Date(), etc., but I keep getting exactly the same result when the input is "16/12/2006"
What's the trick here?
So first, for some reason this is being read in as a factor with a level that is labeled "16/12/2006". You are converting this to a character, so I'll start there.
There are a number of ways to do this, but I think the easiest is to use the lubridate package.
#Install package
install.packages("lubridate")
library(lubridate)
yourTextDate <- "16/12/2006"
yourDate <- dmy(yourTextDate)
yourDate
If you strictly want a Date class, then:
as.Date(s, format='%d/%m/%Y')
## [1] "2006-12-16"
class(.Last.value)
## [1] "Date"
So you can convert the entire column of dates with:
as.Date(epc$Date, format='%d/%m/%Y')
This should work whether it is a character or factor.
lubridate works well as well, but if you're sticking with base R, this works well too.
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"