我有一个数据帧,其特征是具有许多不同的ID。对于每个ID,都有多个事件,这些事件的特征是事件之间的累计持续时间(小时)和该事件的持续时间(秒)。因此,它看起来像:
Id <- c(1,1,1,1,1,1,2,2,2,2,2)
cumulative_time<-c(0,3.58,8.88,11.19,21.86,29.54,0,5,14,19,23)
duration<-c(188,124,706,53,669,1506.2,335,349,395,385,175)
test = data.frame(Id,cumulative_time,duration)
> test
Id cummulative_time duration
1 1 0.00 188.0
2 1 3.58 124.0
3 1 8.88 706.0
4 1 11.19 53.0
5 1 21.86 669.0
6 1 29.54 1506.2
7 2 0.00 335.0
8 2 5.00 349.0
9 2 14.00 395.0
10 2 19.00 385.0
11 2 23.00 175.0
我想按ID分组,然后通过以每10个小时的累积数量进行采样来重组该组,然后以10个小时间隔内的持续时间求和这10个小时。我想要的垃圾箱数量应为0到30小时。这样便有3个垃圾箱。
我查看了cut
函数并设法在数据框中对其进行了修改-甚至对于我作为新用户来说,我也知道它并不漂亮
test_cut = test %>%
mutate(bin_durations = cut(test$cummulative_time,breaks = c(0,10,20,30),labels = c("10","20","30"),include.lowest = TRUE)) %>%
group_by(Id,bin_durations) %>%
mutate(total_duration = sum(duration)) %>%
select(Id,bin_durations,total_duration) %>%
distinct()
给出输出:
test_cut
Id time_bins duration
1 1 10 1018.0
2 1 20 53.0
3 1 30 2175.2
4 2 10 684.0
5 2 20 780.0
6 2 30 175.0
最终,我希望间隔窗口和垃圾箱数量是任意的-如果我的跨度为5000小时,并且我想在1小时内进行垃圾箱采样。为此,我将breaks=seq(0,5000,1)
用作bins
这也将应用于非常大的数据帧,因此在某种程度上需要计算速度。
dplyr解决方案将是一个不错的选择,因为我正在按组应用分箱。
我的猜测是labels = as.character(seq(1,5000,1))
与cut
之间可能存在很好的交互,以生成所需的输出。
谢谢。
经过测试,我发现即使我当前的实现也不像我说的那样:
split
我知道
n=3
test_cut = test %>%
mutate(bin_durations = cut(test$cumulative_time,breaks=seq(0,30,n),labels = as.character(seq(n,30,n)),include.lowest = TRUE)) %>%
group_by(Id,bin_durations) %>%
mutate(total_duration = sum(duration)) %>%
select(Id,bin_durations,total_duration) %>%
distinct()
在bin序列中没有出现的地方,我应该在duration列中将其设为0。而不是遗漏。
因此,它应该看起来像:
test_cut
# A tibble: 11 x 3
# Groups: Id, bin_durations [11]
Id bin_durations total_duration
<dbl> <fct> <dbl>
1 1 3 188
2 1 6 124
3 1 9 706
4 1 12 53
5 1 24 669
6 1 30 1506.
7 2 3 335
8 2 6 349
9 2 15 395
10 2 21 385
11 2 24 175
答案 0 :(得分:1)
这是一个通过整数除法(%/%
)的想法
library(tidyverse)
test %>%
group_by(Id, grp = cumulative_time %/% 10) %>%
summarise(toatal_duration = sum(duration))
给出,
# A tibble: 6 x 3 # Groups: Id [?] Id grp toatal_duration <dbl> <dbl> <dbl> 1 1 0 1018 2 1 1 53 3 1 2 2175. 4 2 0 684 5 2 1 780 6 2 2 175
要解决您的更新问题,我们可以使用complete
来添加缺少的行。因此,对于同一示例,以3的小时为单位进行分箱
test %>%
group_by(Id, grp = cumulative_time %/% 3) %>%
summarise(toatal_duration = sum(duration)) %>%
ungroup() %>%
complete(Id, grp = seq(min(grp), max(grp)), fill = list(toatal_duration = 0))
给出,
# A tibble: 20 x 3 Id grp toatal_duration <dbl> <dbl> <dbl> 1 1 0 188 2 1 1 124 3 1 2 706 4 1 3 53 5 1 4 0 6 1 5 0 7 1 6 0 8 1 7 669 9 1 8 0 10 1 9 1506. 11 2 0 335 12 2 1 349 13 2 2 0 14 2 3 0 15 2 4 395 16 2 5 0 17 2 6 385 18 2 7 175 19 2 8 0 20 2 9 0
答案 1 :(得分:1)
我们可以进行以下更改:
test$cummulative_time
可以简单地是cumulative_time
breaks
,然后如图所示在cut
中使用mutate
可以更改为summarize
,在这种情况下,不需要select
和distinct
group_by
关闭任何ungroup
complete
来为不存在的级别插入0 要实现这些更改,我们需要:
library(dplyr)
library(tidyr)
breaks <- seq(0, 40, 10)
test %>%
mutate(bin_durations = cut(cumulative_time, breaks = breaks,
labels = breaks[-1], include.lowest = TRUE)) %>%
group_by(Id,bin_durations) %>%
summarize(total_duration = sum(duration)) %>%
ungroup %>%
complete(Id, bin_durations, fill = list(total_duration = 0))
给予:
# A tibble: 8 x 3
Id bin_durations total_duration
<dbl> <fct> <dbl>
1 1 10 1018
2 1 20 53
3 1 30 2175.
4 1 40 0
5 2 10 684
6 2 20 780
7 2 30 175
8 2 40 0