Reputation: 293
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
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
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
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