Вычитание секунд из одной строки и установка результата в другую строку в R

#r #time

#r #время

Вопрос:

У меня есть фрейм данных, где первый столбец — время. Мой текущий результат выглядит так:

0:0:0
0:0:0
5:43:42 вечера
5:43:52 вечера

Я пытаюсь заставить часть моего кода искать любые строки, в которых есть значение 0: 0: 0, и вычесть 10 секунд из ближайшей строки со значением в ней. Желаемый результат будет выглядеть следующим образом:

5:43:22 вечера
5:43:32 вечера
5:43:42 вечера
5:43:52 вечера

Я написал эту часть кода, чтобы сделать это за себя. Он выполняется без ошибок, но фактически не изменяет никаких значений.

   entries<-length(data$Time)
  for(j in entries:1)
    if(data[j,1]=="0:0:0"){
      for(k in j-1:1)
        if(data[k,1]!="0:0:0"){
          data[k,1] <- as.POSIXct(data[k,1], format = "%H:%M:%S")
          value <- format(data[k,1]   seconds(10))
          data[j,1] <- value
          break
        }
    }
 

Есть предложения по созданию этого?

Комментарии:

1. Не могли бы вы опубликовать данные, которые вы используете, каковы выходные данные и чего вы хотите достичь?

2. Что происходит, когда время 0: 0: 0 имеет равноудаленные значения с обеих сторон? Могут ли ненулевые значения только следовать за нулевым значением, а не предшествовать нулевому значению?

3. Я обновил вопрос, чтобы уточнить мой текущий результат и желаемый результат, пожалуйста, дайте мне знать, если это все еще неясно, мне сложно сформулировать этот вопрос. У меня могут быть ненулевые значения до и после нулевых значений. Я предполагаю, что я бы создал дополнительный оператор цикла if или for, чтобы исправить эти, но если я ошибаюсь, пожалуйста, не стесняйтесь, дайте мне знать. Я очень новичок в анализе данных и R.

4. «Он работает без ошибок»? Нет, он вообще не запускается, не могли бы вы проверить и отредактировать это, пожалуйста?

Ответ №1:

Предполагая, что последнее значение в ваших данных не будет '0:0:0' , вы можете сделать следующее :

Замените Time на NA то, где находится значение 0:0:0 , и превратите их в POSIXct класс.

 library(dplyr)

df %>%
  mutate(Time = na_if(Time, '0:0:0'), 
         Time1 = as.POSIXct(Time, format = '%T')) -> df1
 

Замените NA значение, вычитая 10 секунд из следующего значения.

 for(i in nrow(df1):1) {
  if(is.na(df1$Time1[i])) {
    df1$Time1[i] <- df1$Time1[i   1] - 10
  }
}
 

Измените POSIXct желаемое format (H: M: S), которое нам нужно.

 df1 %>%
  mutate(Time = format(Time1, '%T'), 
         Time1 = NULL) -> result

result

#      Time
#1 05:43:22
#2 05:43:32
#3 05:43:42
#4 05:43:52
 

данные

 df <- structure(list(Time = c("0:0:0", "0:0:0", "5:43:42", "5:43:52"
)), class = "data.frame", row.names = c(NA, -4L))
 

Ответ №2:

Вот data.table подход, предполагающий, что под «ближайшей строкой со значением» вы подразумеваете ближайшую следующую строку, которая не является «0: 0: 0»:

 library(data.table)
DT <- data.table(Time=c("0:0:0", "0:0:0", "5:43:42 pm", "5:43:52 pm", 
                        "0:0:0", "6:43:52 pm"), c2=LETTERS[1:6])
DT[Time=="0:0:0", Time := NA]
DT[, Time := as.POSIXct(Time, format = "%I:%M:%S %p")]
i <- which(is.na(DT$Time))
DT[, idx:=cumsum(!is.na(Time))]
DT[, idx:=rev(seq(.N)), by=idx]
DT[, Time := nafill(Time, type="nocb")]
DT[i, Time:=Time - (10*idx)][, idx:=NULL]
DT[, Time := format(Time, '%I:%M:%S %p')][]
#>           Time c2
#> 1: 05:43:22 PM  A
#> 2: 05:43:32 PM  B
#> 3: 05:43:42 PM  C
#> 4: 05:43:52 PM  D
#> 5: 06:43:42 PM  E
#> 6: 06:43:52 PM  F
 

Создано 2020-12-30 пакетом reprex (версия 0.3.0)