我想尝试这样的事情
df <- data.frame(times = c("0915", "0930", "0945", "1000", "1015", "1030", "1045", "1100", "1130", "1145", "1200"),
values = c(1,2,3,4,1,2,3,4,1,3,4))
> df
times values
1 0915 1
2 0930 2
3 0945 3
4 1000 4
5 1015 1
6 1030 2
7 1045 3
8 1100 4
9 1130 1
10 1145 3
11 1200 4
12 1215 1
13 1245 3
14 1300 4
15 1330 2
16 1345 4
把它变成这样的东西
> df2
times values
1 0930 3
2 1000 7
3 1030 3
4 1100 7
5 1130 NA
6 1200 7
7 1230 NA
8 1300 7
9 1330 NA
10 1400 NA
基本上,以15分钟的间隔测量值,并将它们转换为30分钟间隔内测量的值(求和就足够了)。
如果我能确定每半小时读一次我有两个15分钟的读数,我可以想出一个好的解决方案。我可以成对添加元素并获得我想要的东西。但我无法确定我的数据集。正如我的演示所示,可能会缺少多个连续值。
所以我认为有必要进行某种数字识别,例如认识到时间是在9:15到9:30之间,并将这两者相加。所以我有一个已经被称为hr2dec
的函数,我创建它来将这些时间转换为十进制,所以它看起来像这样
> hr2dec(df$times)
[1] 9.25 9.50 9.75 10.00 10.25 10.50 10.75 11.00 11.50 11.75 12.00
我提到这个,以防止用十进制而不是4位数时间来解决这个问题。
我也有24小时和多天的数据。因此,如果我有一个循环的解决方案,则需要在0015
之后重置为2400
,因为这些是每天的第一次和最后一次测量。包含日期的完整数据集可以像这样生成(包含时间的小数,就像我说的那样,对我来说也没问题):
set.seed(42)
full_df <- data.frame(date = rep(as.Date(c("2010-02-02", "2010-02-03")), each = 96),
dec_times = seq(0.25,24,0.25),
values = rnorm(96)
)
full_df <- full_df[-c(2,13,15,19,95,131,192),]
到目前为止,我能想出的最佳解决方案是成对比较循环。但即使这样也不完美。
有什么优雅的方式来做我想要的事情吗?即检查第一个和最后一个值(就日期和时间而言),并将每半个小时间隔相加?我对我的循环不满意......
答案 0 :(得分:1)
您应该查看tibbletime
package - 具体来说,您需要查看在一段时间内折叠collapse_by()
个对象的tbl_time
。
library(tibbletime)
library(dplyr)
# create a series of 7 days
# 2018-01-01 to 2018-01-07 by 15 minute intervals
df <- create_series('2018-01-01' ~ '2018-01-07', period = "15 minute")
df$values <- rnorm(nrow(df))
df
#> # A time tibble: 672 x 2
#> # Index: date
#> date values
#> <dttm> <dbl>
#> 1 2018-01-01 00:00:00 -0.365
#> 2 2018-01-01 00:15:00 -0.275
#> 3 2018-01-01 00:30:00 -1.50
#> 4 2018-01-01 00:45:00 -1.64
#> 5 2018-01-01 01:00:00 -0.341
#> 6 2018-01-01 01:15:00 -1.05
#> 7 2018-01-01 01:30:00 -0.544
#> 8 2018-01-01 01:45:00 -1.10
#> 9 2018-01-01 02:00:00 0.0824
#> 10 2018-01-01 02:15:00 0.477
#> # ... with 662 more rows
# Collapse into 30 minute intervals, group, and sum
df %>%
collapse_by("30 minute") %>%
group_by(date) %>%
summarise(sum_values = sum(values))
#> # A time tibble: 336 x 2
#> # Index: date
#> date sum_values
#> <dttm> <dbl>
#> 1 2018-01-01 00:15:00 -0.640
#> 2 2018-01-01 00:45:00 -3.14
#> 3 2018-01-01 01:15:00 -1.39
#> 4 2018-01-01 01:45:00 -1.64
#> 5 2018-01-01 02:15:00 0.559
#> 6 2018-01-01 02:45:00 0.581
#> 7 2018-01-01 03:15:00 -1.50
#> 8 2018-01-01 03:45:00 1.36
#> 9 2018-01-01 04:15:00 0.872
#> 10 2018-01-01 04:45:00 -0.835
#> # ... with 326 more rows
# Alternatively, you can use clean = TRUE
df %>%
collapse_by("30 minute", clean = TRUE) %>%
group_by(date) %>%
summarise(sum_values = sum(values))
#> # A time tibble: 336 x 2
#> # Index: date
#> date sum_values
#> <dttm> <dbl>
#> 1 2018-01-01 00:30:00 -0.640
#> 2 2018-01-01 01:00:00 -3.14
#> 3 2018-01-01 01:30:00 -1.39
#> 4 2018-01-01 02:00:00 -1.64
#> 5 2018-01-01 02:30:00 0.559
#> 6 2018-01-01 03:00:00 0.581
#> 7 2018-01-01 03:30:00 -1.50
#> 8 2018-01-01 04:00:00 1.36
#> 9 2018-01-01 04:30:00 0.872
#> 10 2018-01-01 05:00:00 -0.835
#> # ... with 326 more rows
如果你更喜欢视频(<20分钟),请查看David Vaughan的The Future of Time Series and Financial Analysis in the Tidyverse。
答案 1 :(得分:0)
我是OP。经过一段时间的游戏后,我得到了一些我认为比我原来拥有的循环更优雅的解决方案。决定发布作为讨论的答案。仍然不会介意更优雅的东西。
使用full_df
我创建了一个索引,这就是我提供给我的日子所期望的所有15分钟的时间段。
index <- data.frame(date = rep(seq(full_df$date[1], full_df$date[nrow(full_df)],by="+1 day"),each=96),
dec_times = rep(seq(0.25,24,0.25), length(unique(full_df$date)))
)
然后我将这个与full_df
合并为两个匹配的列,因此保留了不常见的值(即我的缺失值)
index <- merge(full_df, index, by.y=c("date", "dec_times"), all.y=T)
然后我继续创建一个列,列出每个15分钟间隔属于的半小时使用plyr
的{{1}}函数
round_any
然后我使用index$half_hour <- plyr::round_any(index$dec_times, 0.5, ceiling)
的{{1}}函数根据新的plyr
列进行求和(利用任何事物+ NA是NA的事实)。
ddply
我相信结果数据框正是我所追求的。
half_hour
我喜欢这个解决方案
我不喜欢这个解决方案