【问题标题】:Calculating conditional cumulative time计算条件累积时间
【发布时间】:2018-06-30 21:24:19
【问题描述】:

遵循来自this question 的指针。

我想计算所有Cats 的累积时间,考虑它们各自的最后切换状态。

EDIT: 我还想检查Cat 的第一个Toggle 状态是否为Off,如果是这样,对于那个特定的cat,从午夜00:00:00 到第一个第一个关闭时间的时间应该被添加到其总条件累积准时。

样本数据:

       Time Cat Toggle
1  05:12:09  36 On
2  05:12:12 26R Off # First Toggle of this Cat happens to be Off, Condition met
3  05:12:15 26R On
4  05:12:16 26R Off
5  05:12:18  99 Off # Condition met
6  05:12:18  99 On
7  05:12:24  36 Off
8  05:12:26  36 On
9  05:12:29  80 Off # Condition met
10 05:12:30  99 Off
11 05:12:31  95 Off # Condition met
12 05:12:32  36 Off

期望的样本输出:

  Cat Time(Secs)
1 36  21
2 26R 18733 # (=1+18732), 18732 secs to be added = total Sec from midnight till 05:12:12
3 99  18750 # (=12+18738), 18738 secs to be added = total Sec from midnight till 05:12:18
4 ..  ..

感谢任何形式的帮助。

【问题讨论】:

  • 到目前为止你尝试了什么?
  • @camille 为所有猫创建了一个列表(数据框)列表,但由于没有特定的切换顺序,事情没有成功。

标签: r dplyr difftime


【解决方案1】:

使用基础 R:

df$Time=as.POSIXct(df$Time,,"%H:%M:%S")

stack(by(df,df$Cat,function(x)sum(c(0,diff(x$Time))*(x$Toggle=="Off"))))

  values ind
1      1 26R
2     21  36
3      0  80
4      0  95
5     12  99

【讨论】:

    【解决方案2】:

    可以使用as.difftime 函数将时间从H:M:S 格式转换为秒。然后为每个On 雕像找到lead 记录,以便计算从On 流逝的时间间隔。

    library(dplyr)
    
    # Convert Time in seconds.
    df %>% mutate(Time = as.difftime(Time, units = "secs")) %>%
      group_by(Cat) %>%
      mutate(TimeInterVal = ifelse(Toggle == "On", (lead(Time) - Time), 0)) %>%
      summarise(TimeInterVal = sum(TimeInterVal))
    
    
    # # A tibble: 5 x 2
    #   Cat   TimeInterVal
    #   <chr>        <dbl>
    # 1 26R           1.00
    # 2 36           21.0 
    # 3 80            0   
    # 4 95            0   
    # 5 99           12.0 
    

    注意:开可以考虑在Time上排列数据,确保行按时排序。

    数据:

    df <- read.table(text ="
    Time Cat Toggle
    1  05:12:09  36 On
    2  05:12:12 26R Off
    3  05:12:15 26R On
    4  05:12:16 26R Off
    5  05:12:18  99 Off
    6  05:12:18  99 On
    7  05:12:24  36 Off
    8  05:12:26  36 On
    9  05:12:29  80 Off
    10 05:12:30  99 Off
    11 05:12:31  95 Off
    12 05:12:32  36 Off",
    header = TRUE, stringsAsFactors = FALSE)
    

    【讨论】:

    • 感谢 MKR 的快速解决方案,+1。直到TimeInterVal 创建点,虽然在summarise 中它经常产生NAs,但没有问题,尝试处理这些但运气不好
    • @KeyshovBorate 只需将summarise 更改为summarise(TimeInterVal = sum(TimeInterVal, na.rm = TRUE))
    【解决方案3】:

    使用的可能解决方案:

    # load the 'data.table'-package, convert 'df' to a 'data.table'
    # and 'Time'-column to a time-format
    library(data.table)
    setDT(df)[, Time := as.ITime(Time)]
    
    # calculate the time-difference
    df[, .(time.diff = sum((shift(Time, type = 'lead') - Time) * (Toggle == 'On'), na.rm = TRUE))
       , by = Cat]
    

    给出:

       Cat time.diff
    1:  36        21
    2: 26R         1
    3:  99        12
    4:  80         0
    5:  95         0
    

    针对您在 cmets 中的问题,您可以:

    # create a new data.table with midnigth times for the categories where
    # the first 'Toggle' is on "Off"
    df0 <- df[, .I[first(Toggle) == "Off"], by = Cat
              ][, .(Time = as.ITime("00:00:00"), Cat = unique(Cat), Toggle = "On")]
    
    # bind that to the original data.table; order on 'Cat' and 'Time'
    # and then do the same calculation
    rbind(df, df0)[order(Cat, Time)
                   ][, .(time.diff = sum((shift(Time, type = 'lead') - Time) * (Toggle == 'On'), na.rm = TRUE))
                                     , by = Cat]
    

    给出:

       Cat time.diff
    1: 26R     18733
    2:  36        21
    3:  80     18749
    4:  95     18751
    5:  99     18750
    

    基于 R 的替代方案(仅原始问题):

    df$Time <- as.POSIXct(df$Time, format = "%H:%M:%S")
    
    stack(sapply(split(df, df$Cat),
                 function(x) sum(diff(x[["Time"]]) * (head(x[["Toggle"]],-1) == 'On'))))
    

    给出:

      values ind
    1      1 26R
    2     21  36
    3      0  80
    4      0  95
    5     12  99
    

    (仅原始问题):

    library(dplyr)
    library(lubridate)
    
    df %>% 
      mutate(Time = lubridate::hms(Time)) %>% 
      group_by(Cat) %>% 
      summarise(time.diff = sum(diff(Time) * (head(Toggle, -1) == 'On'),
                                na.rm = TRUE))
    

    【讨论】:

    • 谢谢雅普。在创建time.diff 时,如何检查Cat 的第一个Toggle 是否为Off,如果是,我如何添加“从午夜到其首次关闭时间的时间”。
    • @KeyshovBorate 你的意思是对于Cat == 26R,第一个Toggle 必须设置为On,而相应的Time 必须设置为零?您能否根据上述示例数据包含所需的输出?
    • 当然让我补充。不。它基本上是为所有Cats 添加从午夜开始的时间,它的第一个切换为Off - 因为这将是它自午夜以来第一次关闭 - 我们必须将其视为它的时间总准时。
    • 很高兴认识 Jaap :)
    猜你喜欢
    • 1970-01-01
    • 2014-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-03
    • 2019-06-06
    • 1970-01-01
    • 2020-12-17
    相关资源
    最近更新 更多