STL
STL

Reputation: 293

Converting Time to 'HMS" Character Format in R

I have a column of date times formatted like '2000-11-21 10:01:01', 2000-11-21 00:02:01', 2000-11-21 00:00:06. I would like to create a new column that would set the time to an HMS format for example, in the 3 dates above, it would return 'HMS', 'MS', 'S'. I would try doing it the following way but I was wondering if there was an easier way to do it:

ifelse(
  grepl("00:00:", datecolumn), "S", 
        ifelse(grepl("00:", datecolumn), "MS", "HMS")
)

Output:

 datecolumn                 HMS
2000-11-21 10:01:01         HMS
2000-11-21 00:02:01          MS
2000-11-21 00:00:06           S
2000-11-21 00:00:10           S
2000-11-21 00:10:06          MS
2000-11-21 00:00:07           S
2000-11-21 10:00:06         HMS

Upvotes: 2

Views: 1226

Answers (3)

Henrik
Henrik

Reputation: 67818

Convert the time part to data.table::ITime ("a time-of-day class stored as the integer number of seconds in the day"), and cut it with appropriate breaks and labels:

d$HMS <- cut(data.table::as.ITime(d$datecolumn),
             breaks = c(0, 60 - 1, 60 * 60 - 1, Inf),
             labels = c("s", "ms", "hms"))
d
#                     datecolumn HMS
# 1          2000-11-21 10:01:01 hms
# 2          2000-11-21 00:02:01  ms
# 3          2000-11-21 00:00:06   s
# 4          2000-11-21 00:00:10   s
# 5          2000-11-21 00:10:06  ms
# 6          2000-11-21 00:00:07   s
# 7          2000-11-21 10:00:06 hms

Upvotes: 1

hrbrmstr
hrbrmstr

Reputation: 78832

The case_when() function from dplyr can provide a readable alternative to nested ifelse blocks. stringi is not really needed (grepl wld work fine) but I like the expressive nature of stringi function names (and stringr is an unnecessary crutch IMO):

library(stringi)
library(tidyverse)

read.csv(text="datecolumn,HMS
2000-11-21 10:01:01,HMS
2000-11-21 00:02:01,MS
2000-11-21 00:00:06,S
2000-11-21 00:00:10,S
2000-11-21 00:10:06,MS
2000-11-21 00:00:07,S
2000-11-21 10:00:06,HMS", stringsAsFactors=FALSE) -> xdf

Note that order matters here:

mutate(xdf, computed_hms = case_when(
  stri_detect_regex(datecolumn, "00:00:[[:digit:]]{2}") ~ "S",
  stri_detect_regex(datecolumn, "00:[[:digit:]]{2}:[[:digit:]]{2}") ~ "MS",
  stri_detect_regex(datecolumn, "[[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2}") ~ "HMS"
  TRUE ~ NA_character_
))
##            datecolumn HMS computed_hms
## 1 2000-11-21 10:01:01 HMS          HMS
## 2 2000-11-21 00:02:01  MS           MS
## 3 2000-11-21 00:00:06   S            S
## 4 2000-11-21 00:00:10   S            S
## 5 2000-11-21 00:10:06  MS           MS
## 6 2000-11-21 00:00:07   S            S
## 7 2000-11-21 10:00:06 HMS          HMS

Upvotes: 0

SmitM
SmitM

Reputation: 1376

You could use the lubridate package along with paste like this:

require(lubridate)
df$new_col <- paste(ifelse(hour(df$date) > 0, "H", ""), 
                    ifelse(minute(df$date) > 0, "M", ""), 
                    ifelse(second(df$date) > 0, "S", ""), sep = "")

Upvotes: 3

Related Questions