我正在使用记录交互的开始时间和结束时间的数据。我的目标是在特定时间间隔(例如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放入正确的开始和停止列。问题是我不知道如何填写当前会收到零的中间列。
答案 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_time
和end_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