1

I would like to know whether there is a way to change a number on a specific position in a datetime?

I have a dataframe [df] like this:

id    created_at            diff
1     2020-04-08 14:30:47   89  
2     2020-04-08 14:30:47   0
3     2020-04-08 15:30:47   78
4     2020-04-08 15:30:47   0

I would like to change the created_at value for the rows with diff = 0, where I would like to add 10 minutes, or at possibly change number on positon 15 by adding 1.

The desirable result would look like this:

id    created_at            diff
1     2020-04-08 14:30:47   89  
2     2020-04-08 14:40:47   0
3     2020-04-08 15:30:47   78
4     2020-04-08 15:40:47   0

Is there any way of doing this? Thank you very much for any suggestions!

Ric S
  • 9,073
  • 3
  • 25
  • 51
dloudtrain
  • 301
  • 2
  • 9
  • [Adding time to POSIXct object in R](https://stackoverflow.com/questions/11922181/adding-time-to-posixct-object-in-r) – Henrik Jul 13 '20 at 10:43

4 Answers4

1

You can use code like this:

library(dplyr)
library(lubridate)

df %>% mutate(created_at = if_else(diff == 0, created_at + minutes(1), created_at))
Ric S
  • 9,073
  • 3
  • 25
  • 51
Kevin_Nguyen
  • 112
  • 6
  • 1
    This solution implies that the variable `created_at` is not of `character` type, but `POSIXct`. You should do `df$created_at <- ymd_hms(df$created_at)` first, or convert it inside the `mutate` pipeline – Ric S Jul 13 '20 at 10:40
1

Assuming the created_by column is a string (type character), you can convert it to a date/time, add 10 minutes, then convert back to string:

# Which rows to modify
r = which(df$diff == 0)

# read the created_at column, and convert to date/time
v = as.POSIXlt( df[r, 'created_at'])

# Add 10 minutes (10*60 seconds)
v = v + 10*60

# write values back (as string)
df[r,'created_at'] = as.character(v)

You can combine them into two lines:

r = which(df$diff==0)
df[r, 'created_at'] = as.character(as.POSIXlt(df[r, 'created_at']) + 10*60)

Resulting in:

  id          created_at diff
   1 2020-04-08 14:30:47   89
   2 2020-04-08 14:40:47    0
   3 2020-04-08 15:30:47   78
   4 2020-04-08 15:40:47    0
Aziz
  • 20,065
  • 8
  • 63
  • 69
1

One possible solution using the lubridate package is to first transform the created_at variable in a standard format (POSIXct) and then add 10 minutes only to a subset of the original dataframe, when the condition diff == 0 is verified.

library(lubridate)

df$created_at <- ymd_hms(df$created_at)
df[df$diff == 0, "created_at"] <- df[df$diff == 0, "created_at"] + minutes(10)

Output

#   id          created_at diff
# 1  1 2020-04-08 14:30:47   89
# 2  2 2020-04-08 14:40:47    0
# 3  3 2020-04-08 15:30:47   78
# 4  4 2020-04-08 15:40:47    0
Ric S
  • 9,073
  • 3
  • 25
  • 51
0

Perhaps not the simplest, but this regex solution works:

df$created_at[df$difference == 0] <- 
  paste(sub("(^[^:]+:).*", "\\1", df$created_at[df$difference == 0]), 
        as.numeric(sub(".*\\d{2}:(\\d{2}):\\d{2}", "\\1", df$created_at[df$difference == 0])) +10,
        sub(".*(:\\d{2}).*$", "\\1", df$created_at[df$difference == 0]), sep = "")

Explanation:

First you target the date values associated with difference == 0. To these values you apply the following operations, namely

  1. cut the dates into relevant pieces (everything before the minutes, the minutes themselves, everything after the minutes),
  2. perform the sought change (adding 10 min), and
  3. paste the strings back together.

The only complicating factor is that in order for you to add the value 10 to the minutes, what the regex returns must be converted to type numeric:

Result:

df
           created_at difference
1 2020-04-08 14:30:47         89
2 2020-04-08 14:43:55          0
3 2020-04-08 14:37:02          2
4 2020-04-08 14:51:15          0

Data:

df <- data.frame(
  created_at = c("2020-04-08 14:30:47", "2020-04-08 14:33:55", "2020-04-08 14:37:02", "2020-04-08 14:41:15"),
  difference = c(89, 0, 2, 0), stringsAsFactors = F
)
Chris Ruehlemann
  • 20,321
  • 4
  • 12
  • 34