用多列时间测量时间量

时间:2019-01-22 20:00:43

标签: r time

我正在使用记录交互的开始时间和结束时间的数据。我的目标是在特定时间间隔(例如12:00、12:30、13:00)测量音量。我的目标实质上是进行逻辑检查,以查看时间范围(在这种情况下为小时数)是否适合由两列表示的时间范围。数据看起来像这样


client       start_time     end_time
smith          08:00          10:15
coven          09:30          10:25
peter          07:35          11:30


The result I would like would look like this

time         count
07:00          0
07:30          1
08:00          2
08:30          2
09:00          2
09:30          3
10:00          3
10:30          1
11:00          1
11:30          1

我知道我可以在Excel中手动完成此操作,但是有两千行,我希望它可以重现。我已经在Google上搜索了很多,但找不到答案。我希望有人能指出我正确的方向

我的第一个想法是通过使用mutate将列真正扩大。我将时间转换为整数,以使使用它们变得更容易。可以,但是非常缓慢,最后我仍然需要找到一种方法来填补中间的缺失时间。

我曾经考虑过在内部使用,但是我看不出是否可以在这里使用它。

这是现在的代码。


library(tidyverse)

df1 <- df1 %>%
  mutate(eight_ = ifelse(start_num >= 480 & start_num <= 539 | end_num >= 480 & end_num <= 539 , 1, 0))

代码按预期工作,它将1放入正确的开始和停止列。问题是我不知道如何填写当前会收到零的中间列。

2 个答案:

答案 0 :(得分:0)

我确信必须有一种更简单的方法来实现它,但这是我使用tidyverse的解决方案:

df %>%
 group_by(client) %>%
 do(data.frame(time = seq(as.POSIXct(.$start_time, format = "%H:%M"),
               as.POSIXct(.$end_time, format = "%H:%M"), by = "min"),
               temp = 0)) %>%
 complete(time = seq(as.POSIXct("07:00:00", format = "%H:%M:%S"),
                     as.POSIXct("11:30:00", format = "%H:%M:%S"), by = "min")) %>%
 mutate(time = round_date(time, unit = "30minutes")) %>%
 group_by(client, time) %>%
 summarise(temp = ifelse(any(temp == 0), 1, 0)) %>%
 group_by(time) %>%
 summarise(count = sum(temp, na.rm = TRUE))

   time                count
   <dttm>              <dbl>
 1 2019-01-22 07:00:00    0.
 2 2019-01-22 07:30:00    1.
 3 2019-01-22 08:00:00    2.
 4 2019-01-22 08:30:00    2.
 5 2019-01-22 09:00:00    2.
 6 2019-01-22 09:30:00    3.
 7 2019-01-22 10:00:00    3.
 8 2019-01-22 10:30:00    3.
 9 2019-01-22 11:00:00    1.
10 2019-01-22 11:30:00    1.

首先,它会按照从“ start_time”到“ end_time”的微小顺序为每个客户端扩展原始df。在所有分钟中,“ temp”变量都分配为零。其次,通过使用complete(),它会创建一个具有指定起点和终点的分钟序列。因此,在给定时间序列的某些部分中没有数据的客户端将在“ temp”变量上具有NA,否则为0。第三,使用round_date(),它将“ time”变量中的时间舍入到30分钟。第四,它按“客户”和“时间”分组,并评估“温度”中是否有0。如果是这样,它将分配1,否则将分配0。最后,它将按“时间”分组并返回1的总和,表示在给定的时间间隔内发生了一次。

样本数据:

df <- read.table(text = "client       start_time     end_time
smith          08:00          10:15
coven          09:30          10:25
peter          07:35          11:30", header = TRUE, stringsAsFactors = FALSE)

答案 1 :(得分:0)

这是一个将start_timeend_time的间隔扩展30 minute并计算结果的解决方案。

library(tidyverse)
library(lubridate)

df <- tibble(
  client = c("smith", "coven", "peter"),
  start_time = c("08:00", "09:30", "07:35"),
  end_time = c("10:15", "10:25", "11:30")
)

df %>% 
  mutate(
    start_time = floor_date(as.POSIXct(start_time, format = '%H:%M', tz = 'UTC'), unit = '10 minutes'),
    end_time = floor_date(as.POSIXct(end_time, format = '%H:%M', tz = 'UTC'), unit = '10 minutes'),
  ) %>%
  nest(start_time, end_time) %>%
  mutate(time = map(data, ~seq(unique(.x$start_time), unique(.x$end_time), unit = 'min', by = '30 min'))) %>%
  unnest(time) %>% 
  mutate(time = format(time, '%H:%M')) %>% 
  group_by(time) %>% 
  tally()

# A tibble: 9 x 2
  time      n
  <chr> <int>
1 07:30     1
2 08:00     2
3 08:30     2
4 09:00     2
5 09:30     3
6 10:00     3
7 10:30     1
8 11:00     1
9 11:30     1

如果您需要从07:00 to 11:30开始的完整时间间隔,可以执行以下操作:

df %>%
  mutate(
    start_time = floor_date(as.POSIXct(start_time, format = "%H:%M", tz = "UTC"), unit = "10 minutes"),
    end_time = floor_date(as.POSIXct(end_time, format = "%H:%M", tz = "UTC"), unit = "10 minutes"),
  ) %>%
  nest(start_time, end_time) %>%
  mutate(time = map(data, ~ seq(unique(.x$start_time), unique(.x$end_time), unit = 'min', by = '30 min'))) %>%
  unnest(time) %>%
  mutate(time = format(time, "%H:%M")) %>%
  group_by(time) %>%
  tally() %>% 
  right_join( # add full sequence of time intervals
    tibble(time = seq(
      as.POSIXct("07:00", format = "%H:%M", tz = "UTC"),
      as.POSIXct("11:30", format = "%H:%M", tz = "UTC"), 
      unit = 'min', by = '30 min'
    )) %>%
      mutate(time = format(time, "%H:%M")),
    by = 'time'
  )

# A tibble: 10 x 2
   time      n
   <chr> <int>
 1 07:00    NA
 2 07:30     1
 3 08:00     2
 4 08:30     2
 5 09:00     2
 6 09:30     3
 7 10:00     3
 8 10:30     1
 9 11:00     1
10 11:30     1