How to add seconds to time column - r

I have a "Time" column in R with a set of character time values in HH:MM:SS
However, some of the times do not have the seconds, which makes conversion from char to chron() impossible
Example:
library(chron)
x <- c("08:25:18","08:25","08:24:57","08:24:47")
I want to convert x to chron(), but without the seconds it converts that value to N/A
How can I add :00 seconds to just those that need it? Thanks

We could convert to date time, format it and then apply the times
library(chron)
library(lubridate)
out1 <- times(format(parse_date_time(x, c('HMS', 'HM')), "%H:%M:%S"))
str(out1)
#'times' num [1:4] 08:25:18 08:25:00 08:24:57 08:24:47
# - attr(*, "format")= chr "h:m:s"
Or specify the times in chron
chron(times = format(parse_date_time(x, c('HMS', 'HM')), "%H:%M:%S"))
Or use as.ITime from data.table which would work
library(data.table)
as.ITime(x)
#[1] "08:25:18" "08:25:00" "08:24:57" "08:24:47"

Related

How to convert 09:35:36 from integer to time format?

I have the following data. order.time is integer format. How to I convert it into time format, without adding date?
order.time
9:58:58
9:58:26
9:56:28
9:56:18
9:56:12
I have tried using parse_date_time, strptime, but all the functions add date and time zone in the final data. I only want to convert time from integer format to a format where I can draw plots with time in the x-axis
In the tidyverse, the hms package provides an S3 class for time of day:
> time <- hms::as_hms(c("9:58:58", "9:58:26", "9:56:28", "9:56:18", "9:56:12"))
> time
09:58:58
09:58:26
09:56:28
09:56:18
09:56:12
> class(time)
[1] "hms" "difftime"
> str(time)
'hms' num [1:5] 09:58:58 09:58:26 09:56:28 09:56:18 ...
- attr(*, "units")= chr "secs"
The function as_hms() also takes integer arguments, but only in seconds:
> (time_in_hours <- c(6, 9, 12))
[1] 6 9 12
> hms::as_hms(time_in_hours * 3600)
06:00:00
09:00:00
12:00:00
I would check out the anytime package. It works almost all of the time.
library(anytime)
order.time <- anytime(order.time)
Use as.POSIXct():
times <- as.POSIXct(c('9:58:58', 9:58:26), format = '%H:%M:%S')
Then you will have a time object, i.e: times[2] - times[1] will give you: Time diff of -32 secs.
You can plot these as is, also they can be formatted by using format(x, format).
Ex: format(times[1], format = '%H:%M:%S') will give you '09:58:58'.

R: Turning a string of h:m:s to the corresponding time object

Say I have a column in my data frame containing only objects of strings:
"00:20:10"
"02:12:10"
etc
I want to just convert these strings to the corresponding time type object (in chron library) so I can do things like calculate the mean time etc. How can I do this?
My attempt is just do times(data column) but I get a decimal value.
Just for simplification, I'll assume a data.frame with just a single column. Note that even though it displays as the correct time format, the underlying data is still a decimal value.
library("chron")
mydf <- data.frame(time = c("00:20:10", "02:12:10"), stringsAsFactors = FALSE)
mydf[] <- lapply(mydf,times)
mydf
time
1 00:20:10
2 02:12:10
str(mydf)
'data.frame': 2 obs. of 1 variable:
$ time:Class 'times' atomic [1:2] 0.014 0.0918
.. ..- attr(*, "format")= chr "h:m:s"
as.POSIXct('00:20:10', format='%H:%M:%S')
[1] "2016-06-23 00:20:10 EDT"
as.POSIXct('2:12:10', format='%H:%M:%S')
[1] "2016-06-23 02:12:10 EDT"
You can also specify date, by
as.POSIXct('06/23/2016 00:20:10', format='%m/%d/%Y %H:%M:%S')
[1] "2016-06-23 00:20:10 EDT"

Date time conversion and extract only time

Want to change the class for Time to POSIXlt and extract only the hours minutes and seconds
str(df3$Time)
chr [1:2075259] "17:24:00" "17:25:00" "17:26:00" "17:27:00" ...
Used the strptime function
df33$Time <- strptime(df3$Time, format = "%H:%M:%S")
This gives the date/time appended
> str(df3$Time)
POSIXlt[1:2075259], format: "2015-08-07 17:24:00" "2015-08-07 17:25:00" "2015-08-07 17:26:00" ...
Wanted to extract just the time without changing the POSIXlt class. using the strftime function
df3$Time <- strftime(df3$Time, format = "%H:%M:%S")
but this converts the class back to "char" -
> class(df3$Time)
[1] "character"
How can I just extract the time with class set to POSIX or numeric...
If your data is
a <- "17:24:00"
b <- strptime(a, format = "%H:%M:%S")
you can use lubridate in order to have a result of class integer
library(lubridate)
hour(b)
minute(b)
# > hour(b)
# [1] 17
# > minute(b)
# [1] 24
# > class(minute(b))
# [1] "integer"
and you can combine them using
# character
paste(hour(b),minute(b), sep=":")
# numeric
hour(b) + minute(b)/60
for instance.
I would not advise to do that if you want to do any further operations on your data. However, it might be convenient to do that if you want to plot the results.
A datetime object contains date and time; you cannot extract 'just time'. So you have to think throught what you want:
POSIXlt is a Datetime representation (as a list of components)
POSIXct is a different Datetime representation (as a compact numeric)
Neither one omits the Date part. Once you have a valid object, you can choose to display only the time. But you cannot make the Date part disappear from the representation.
A "modern" tidyverse answer to this is to use hms::as_hms()
For example
library(tidyverse)
library(hms)
as_hms(1)
#> 00:00:01
as_hms("12:34:56")
#> 12:34:56
or, with your example data:
x <- as.POSIXlt(c("17:24:00", "17:25:00", "17:26:00", "17:27:00"), format = "%H:%M:%S")
x
#>[1] "2021-04-10 17:24:00 EDT" "2021-04-10 17:25:00 EDT" "2021-04-10 17:26:00 EDT" "2021-04-10 17:27:00 EDT"
as_hms(x)
# 17:24:00
# 17:25:00
# 17:26:00
# 17:27:00
See also docs here:
https://hms.tidyverse.org/reference/hms.html
You can also use the chron package to extract just times of the day:
library(chron)
# current date/time in POSIXt format as an example
timenow <- Sys.time()
# create chron object "times"
onlytime <- times(strftime(timenow,"%H:%M:%S"))
> onlytime
[1] 14:18:00
> onlytime+1/24
[1] 15:18:00
> class(onlytime)
[1] "times"
This is my idiom for getting just the timepart from a datetime object. I use floor_date() from lubridate to get midnight of the timestamp and take the difference of the timestamp and midnight of that day. I create and store a hms object provided with lubridate (I believe) in dataframes because the class has formatting of hh:mm:ss that is easy to read, but the underlying value is a numeric value of seconds. Here is my code:
library(tidyverse)
library(lubridate)
#>
#> Attaching package: 'lubridate'
#> The following object is masked from 'package:base':
#>
#> date
# Create timestamps
#
# Get timepart by subtacting the timestamp from it's floor'ed date, make sure
# you convert to seconds, and then cast to a time object provided by the
# `hms` package.
# See: https://www.rdocumentation.org/packages/hms/versions/0.4.2/topics/hms
dt <- tibble(dt=c("2019-02-15T13:15:00", "2019-02-19T01:10:33") %>% ymd_hms()) %>%
mutate(timepart = hms::hms(as.numeric(dt - floor_date(dt, "1 day"), unit="secs")))
# Look at result
print(dt)
#> # A tibble: 2 x 2
#> dt timepart
#> <dttm> <time>
#> 1 2019-02-15 13:15:00 13:15
#> 2 2019-02-19 01:10:33 01:10
# `hms` object is really a `difftime` object from documentation, but is made into a `hms`
# object that defaults to always store data in seconds.
dt %>% pluck("timepart") %>% str()
#> 'hms' num [1:2] 13:15:00 01:10:33
#> - attr(*, "units")= chr "secs"
# Pull off just the timepart column
dt %>% pluck("timepart")
#> 13:15:00
#> 01:10:33
# Get numeric part. From documentation, `hms` object always stores in seconds.
dt %>% pluck("timepart") %>% as.numeric()
#> [1] 47700 4233
Created on 2019-02-15 by the reprex package (v0.2.1)
If you want it in POSIX format, the only way would be to leave it as it is, and extract just the "time" part everytime you display it. But internally it will always be date + time anyway.
If you want it in numeric, however, you can simply convert it into a number.
For example, to get time as number of seconds passed since the beginning of the day:
df3$Time=df3$Time$sec + df3$Time$min*60 + df3$Time$hour*3600

How to convert dates in a dataframe to a Date datatype?

I've imported one date value into R:
dtime <- read.csv("dtime.csv", header=TRUE)
It's output (7th Nov, 2013) is printed as:
> dtime
Date
1 07-11-2013 23:06
and also its class is 'factor'.
> class(dtime$Date)
[1] "factor"
Now, I want to extract the time details (hours, minutes, seconds) from the data. So, I was trying to convert the dataframe's date value to Date type. But none of the following commands worked:
dtime <- as.Date(as.character(dtime),format="%d%m%Y")
unclass(as.POSIXct(dtime))
as.POSIXct(dtime$Date, format = "%d-%m-%Y %H:%M:%S")
How do I achieve this in R???
Your attempts didn't work because the format specified was wrong.
With base R there are two possible ways of solving this, with as.POSIXlt
Res <- as.POSIXlt(dtime$Date, format = "%d-%m-%Y %H:%M")
Res$hour
Res$min
Also, for more options, see
attr(Res, "names")
## [1] "sec" "min" "hour" "mday" "mon" "year" "wday" "yday" "isdst" "zone" "gmtoff"
Or a bit less conveniently with as.POSIXct
Res2 <- as.POSIXct(dtime$Date, format = "%d-%m-%Y %H:%M")
format(Res2, "%H") # returns a character vector
format(Res2, "%M") # returns a character vector
I would like to contribute solution utilising lubridate :
dates <- c("07-11-2013 23:06", "08-10-2012 11:11")
dta <- data.frame(dates)
require(lubridate)
dta$properDate <- dmy_hm(dta$dates)
If needed, lubridate will enable you to conveniently specify time zones or extract additional information.

Convert "Jan.2008" to date variable

How would I convert the following character variables to dates?
strDates <- c("Jan.2008", "Feb.2008")
str(strDates)
chr [1:2] "Jan.2008" "Feb.2008"
dates <- as.Date(strDates, "%b %Y")
str(dates)
Date[1:2], format: NA NA
Any assistance would be greatly appreciated
To form a valid 'date', you also need a day which your data was lacking. So we add one, and we simply use an arbitrary day (here: first of the month):
R> strDates <- c("Jan.2008", "Feb.2008")
R> strptime(paste("01", strDates), "%d %b.%Y")
[1] "2008-01-01" "2008-02-01"
R>
A Date requires a day element as well, so you can add that to the input string with paste:
full.dates <- paste("01", strDates, sep = ".")
Specify the template correctly, including separator tokens:
as.Date(full.dates, "%d.%b.%Y")
[1] "2008-01-01" "2008-02-01"

Resources