Рассчитать разницу во времени в формате% H:% M:% S в R - PullRequest
3 голосов
/ 08 апреля 2020

Я пытаюсь вычислить разницу во времени между двумя столбцами для строк, в которых выполняется определенный критерий.

dates1 <- c("1899-12-31 12:20:00 PMT", "1899-12-31 15:30:00 PMT", "1899-12-31 13:20:00 PMT", "1899-12-31 11:50:00 PMT",
             NA)   

dates2 <- c("1899-12-31 11:13:00 PMT", "1899-12-31 11:41:00 PMT", "1899-12-31 14:04:00 PMT", "1899-12-31 13:03:00 PMT", 
            "1899-12-31 13:18:00 PMT")

site <- c(15, 16, 18, 18,
          15)

DS <- as.data.frame(cbind(site, dates1 , dates2))

## convert to POSIXct format
DS[, 2:3] <- lapply(DS[, 2:3], function(x) as.POSIXct(strptime(x,"%Y-%m-%d %H:%M:%S ",tz="")))

## create a new columns with the time difference between dates1 and dates2 in %H:%M:%S format if site=18 , else take value from column dates1
DS$output <- ifelse(DS$site ==18, 
                      difftime(DS$dates1, DS$dates2, units = "mins"),
                      DS$dates1) 

## using the code above doesnt work because:
#1- using the difftime function I can't choose the "%H:%M:%S" for the output
#2- for sites != 18, the dates1 lose its "%H:%M:%S format


# I have also tried to use:
DS$output <- ifelse(DS$site ==18, 
                      difftime(DS$dates1, DS$dates2, units = "mins"),
                      0) 
## and then convert the difference in minutes to %H:%M:%S format using
DS$output<- as.difftime(DS$output , format = "%H:%M:%S", units = "mins")

## but it doesnt work.

## the output should be something like:

output<- c("12:20:00", "15:30:00","00:44:00", "01:13:00", NA)

DS.out <- cbind(DS, output)

> DS.out 
  site                  dates1                  dates2   output
1   15 1899-12-31 12:20:00 PMT 1899-12-31 11:13:00 PMT 12:20:00
2   16 1899-12-31 15:30:00 PMT 1899-12-31 11:41:00 PMT 15:30:00
3   18 1899-12-31 13:20:00 PMT 1899-12-31 14:04:00 PMT 00:44:00
4   18 1899-12-31 11:50:00 PMT 1899-12-31 13:03:00 PMT 01:13:00
5   15                    <NA> 1899-12-31 13:18:00 PMT     <NA>

    #Where output is the time difference calculated for rows 3 and 4 (site=18) 
#or a copy of the time from dates 1 for the other rows (with sites different from 18). 

Есть ли способ расчета разницы во времени в формате H%:% M:% S с использованием другой функции?

Ответы [ 3 ]

0 голосов
/ 08 апреля 2020

Вы можете использовать формат "times" из библиотеки chron.

(это не очень просто, но, похоже, работает)

# get the difference in minutes
DS$Time1NEW <- ifelse(DS$site ==18, 
                      difftime(DS$dates1, DS$dates2, units = "mins"),
                      NA) 

# get the absolute value
DS$Time1NEW<-abs(DS$Time1NEW)

# conver to hours:min:sec using "times" from library chron
DS$hours_minutes<-times((DS$Time1NEW%/%60 +  DS$Time1NEW%%60 /60)/24)

# convert the others (not in site 18)
DS$no18<-times(paste0(hours(DS$dates1),':', minutes(DS$dates1),':', seconds(DS$dates1)))

# create final data column
DS$final<-DS$hours_minutes

# now substitute when necessary
wh<-which(is.na(DS$final))
DS$final[wh]<-DS$no18[wh]

И вот что вы получаете:

> head(DS)
  site                  dates1                  dates2 Time1NEW hours_minutes     no18    final
1   15 1899-12-31 12:20:00 PMT 1899-12-31 11:13:00 PMT       NA          <NA> 12:20:00 12:20:00
2   16 1899-12-31 15:30:00 PMT 1899-12-31 11:41:00 PMT       NA          <NA> 15:30:00 15:30:00
3   18 1899-12-31 13:20:00 PMT 1899-12-31 14:04:00 PMT       44      00:44:00 13:20:00 00:44:00
4   18 1899-12-31 11:50:00 PMT 1899-12-31 13:03:00 PMT       73      01:13:00 11:50:00 01:13:00
5   15                    <NA> 1899-12-31 13:18:00 PMT       NA          <NA>     <NA>     <NA>
0 голосов
/ 08 апреля 2020

Вы можете использовать difftime по часам; floor и %% 1 из этого дают часы и минуты, чтобы быть paste d вместе. Однако требуется некоторое округление.

DS$output[DS$site == 18] <- {
  tmp <- as.numeric(round(with(DS[DS$site == 18, ], difftime(dates2, dates1, units="hours")), 2))
  paste(sprintf("%02d", floor(tmp)), round(tmp %% 1 * 60), "00", sep=":")
}
DS$output[site != 18] <- strftime(DS$dates1[DS$site != 18], "%T")
DS
#   site              dates1              dates2   output
# 1   15 1899-12-31 12:20:00 1899-12-31 11:13:00 12:20:00
# 2   16 1899-12-31 15:30:00 1899-12-31 11:41:00 15:30:00
# 3   18 1899-12-31 13:20:00 1899-12-31 14:04:00 00:44:00
# 4   18 1899-12-31 11:50:00 1899-12-31 13:03:00 01:13:00
# 5   15                <NA> 1899-12-31 13:18:00     <NA>
0 голосов
/ 08 апреля 2020

Хотелось бы что-нибудь подобное?

with(DS, ifelse(site == 18, as.character(lubridate::seconds_to_period(
                difftime(dates2, dates1, units = "secs"))), 
                format(dates1, "%T")))

#[1] "12:20:00"  "15:30:00"  "44M 0S"    "1H 13M 0S" NA   
...