我希望在每个15分钟间隔(即12:00:00 AM,12:15:00 AM,12:30:00AM)中获取最接近的先前读数,以获取间隔之间的任意数量的读数。 / p>
例如,我希望拥有df
:
Timestamp Value (kW)
8/12/2018 23:00:06 51
8/13/2018 0:00:16 52
8/13/2018 0:10:26 53
8/13/2018 0:14:36 54
8/13/2018 0:15:00 55
8/13/2018 0:19:57 56
8/13/2018 0:29:09 57
8/13/2018 0:38:17 58
8/13/2018 0:44:59 59
8/13/2018 0:45:00 60
8/13/2018 0:58:47 61
8/13/2018 1:01:57 62
structure(list(Timestamp = c("8/12/2018 23:00:00", "8/13/2018 0:00:00",
"8/13/2018 0:10:00", "8/13/2018 0:14:00", "8/13/2018 0:15:00",
"8/13/2018 0:19:00", "8/13/2018 0:29:00", "8/13/2018 0:38:00",
"8/13/2018 0:44:00", "8/13/2018 0:45:00", "8/13/2018 0:58:00",
"8/13/2018 1:01:00"), Value..kW. = 51:62), .Names = c("Timestamp",
"Value..kW."), class = "data.frame", row.names = c(NA, -12L))
寻找更接近df2
的地方:
Interval Value
8/13/2018 0:00:00 51
8/13/2018 0:15:00 55
8/13/2018 0:30:00 57
8/13/2018 0:45:00 60
8/13/2018 1:00:00 61
也请注意seconds
。
我认为nalocf
和zoo
或dplyr
的{{1}}函数可以帮助我。打开其他软件包。
答案 0 :(得分:4)
对于使用{nearest“选项的data.table
滚动连接来说,这可能是一个很好的应用。
第一步是将数据放入具有正确格式的data.table
时间戳记的POSIXct
类型的对象中。
library(data.table)
DT <- structure(list(Timestamp = c("8/12/2018 23:00:00", "8/13/2018 0:00:00",
"8/13/2018 0:10:00", "8/13/2018 0:14:00", "8/13/2018 0:15:00",
"8/13/2018 0:19:00", "8/13/2018 0:29:00", "8/13/2018 0:38:00",
"8/13/2018 0:44:00", "8/13/2018 0:45:00", "8/13/2018 0:58:00",
"8/13/2018 1:01:00"), Value..kW. = 51:62), .Names = c("Timestamp",
"Value..kW."), class = "data.frame", row.names = c(NA, -12L))
## Convert from data.frame to data.table
setDT(DT)
## Convert to POSIXct
DT[,Timestamp := as.POSIXct(Timestamp, format = "%m/%d/%Y %H:%M:%S", tz = "UTC")]
一旦有了,就可以以15分钟的间隔序列生成另一个表。
## Get Start and Ends
Start <- min(as.POSIXct(cut.POSIXt(DT[,Timestamp],breaks = c("15 min")), tz = "UTC"))
End <- max(as.POSIXct(cut.POSIXt(DT[,Timestamp],breaks = c("15 min")), tz = "UTC"))
## Generate data.table with a sequence
SummaryDT <- data.table(TimeStamp15 = seq.POSIXt(from = Start, to = End, by = "15 min"))
print(SummaryDT)
# TimeStamp15
# 1: 2018-08-12 23:00:00
# 2: 2018-08-12 23:15:00
# 3: 2018-08-12 23:30:00
# 4: 2018-08-12 23:45:00
# 5: 2018-08-13 00:00:00
# 6: 2018-08-13 00:15:00
# 7: 2018-08-13 00:30:00
# 8: 2018-08-13 00:45:00
# 9: 2018-08-13 01:00:00
然后,您可以设置键并使用滚动连接更新获得每15分钟一次的最接近值。
## Set keys
setkey(SummaryDT,TimeStamp15)
setkey(DT,Timestamp)
## Create a new column in SummaryDT with the closest measurement
SummaryDT[DT, Closest_Value_kW := `i.Value..kW.` , roll = "nearest"]
print(SummaryDT)
# TimeStamp15 Closest_Value_kW
# 1: 2018-08-12 23:00:00 51
# 2: 2018-08-12 23:15:00 NA
# 3: 2018-08-12 23:30:00 NA
# 4: 2018-08-12 23:45:00 NA
# 5: 2018-08-13 00:00:00 52
# 6: 2018-08-13 00:15:00 56
# 7: 2018-08-13 00:30:00 57
# 8: 2018-08-13 00:45:00 60
# 9: 2018-08-13 01:00:00 62
如果您是data.table
的新手,那么您可能需要了解很多内容,此示例位于频谱的高端-data.table
网站上的Getting Started页面如果您以前从未使用过data.table
,则可能是一个不错的起点。
执行help("data.table")
可以使您的文章简洁明了,但是有一个很好的例子,说明了Ben Gorman在他的博客上写的一些功能– Gorman Analysis: R – Data.Table Rolling Joins,而Rober Norberg在他的博客bRogramming: Understanding data.table Rolling Joins可能有助于更好地理解。
更新:您似乎可能只希望进行结转观察,而不一定要执行“最近”值-在这种情况下,选项如下:
(使用相同的DT
作为起点)
## Get Start and Ends
Start <- min(as.POSIXct(cut.POSIXt(DT[,Timestamp],breaks = c("15 min")), tz = "UTC"))
End <- max(as.POSIXct(cut.POSIXt(DT[,Timestamp],breaks = c("15 min"),), tz = "UTC"))
## Generate data.table with a sequence
SummaryDT <-data.table(TimeStamp15 = seq.POSIXt(from = Start, to = End, by = "15 min"))
## Set keys
setkey(SummaryDT,TimeStamp15)
setkey(DT,Timestamp)
## Do a rolling join
FinalDT <- DT[SummaryDT, roll = +Inf]
print(FinalDT)
# Timestamp Value..kW.
# 1: 2018-08-12 23:00:00 51
# 2: 2018-08-12 23:15:00 51
# 3: 2018-08-12 23:30:00 51
# 4: 2018-08-12 23:45:00 51
# 5: 2018-08-13 00:00:00 52
# 6: 2018-08-13 00:15:00 55
# 7: 2018-08-13 00:30:00 57
# 8: 2018-08-13 00:45:00 60
# 9: 2018-08-13 01:00:00 61
答案 1 :(得分:1)
这可能与示例结果有所不同。我不确定您的示例输出是否100%正确。例如12/8中的数据呢?
润滑剂润滑脂具有许多有用的日期时间功能。这会将字符转换为日期,并四舍五入到最接近的句点。 (还有floor_date
和ceiling_date
函数,分别向下或向上取整)。
library(dplyr)
library(lubridate)
df %>%
# ensure timestamp is a date type and round to the nearest fifteen minutes
mutate(ts = mdy_hm(Timestamp),
period = round_date(ts, unit = "15 minutes")) %>%
# group into periods
group_by(period) %>%
# grab the first row in each period, orderd by the timestamp (use -1 for last)
top_n(-1, ts) %>%
# order the reuslt
arrange(period)
# Timestamp Value..kW. ts period
# <chr> <int> <dttm> <dttm>
# 1 8/12/2018 23:00 51 2018-08-12 23:00:00 2018-08-12 23:00:00
# 2 8/13/2018 0:00 52 2018-08-13 00:00:00 2018-08-13 00:00:00
# 3 8/13/2018 0:10 53 2018-08-13 00:10:00 2018-08-13 00:15:00
# 4 8/13/2018 0:29 57 2018-08-13 00:29:00 2018-08-13 00:30:00
# 5 8/13/2018 0:38 58 2018-08-13 00:38:00 2018-08-13 00:45:00
答案 2 :(得分:1)
根据输入数据的结构和预期的约束,OP有多种选择。
从问题和样本数据集中,如果输入数据包含空白(即间隔超过15分钟且未记录任何数据),则尚不清楚完全预期的结果。 OP如何希望输入数据中的差距反映在结果中?
编辑: 。OP提供了两个略有不同的数据集。两者都在下面用来说明输入数据对结果的影响。
下面的变体将使用lubridate
和data.table
。假定df
已被Timesstamp
排序。
所有变体都需要它:
library(lubridate)
library(data.table)
setDT(df)[, Timestamp := mdy_hms(Timestamp)]
最简单的解决方案是加入下一个15分钟间隔:
df[, .SD[.N], by = .(Interval = ceiling_date(Timestamp, "15 min"))]
Interval Value..kW. 1: 2018-08-12 23:00:00 51 2: 2018-08-13 00:00:00 52 3: 2018-08-13 00:15:00 55 4: 2018-08-13 00:30:00 57 5: 2018-08-13 00:45:00 60 6: 2018-08-13 01:00:00 61 7: 2018-08-13 01:15:00 62
请注意,第1行和第2行之间存在1小时的间隔,其中缺少3个间隔。
为了完整起见,这是一个变体,它也适用于无序数据。
df[, .SD[which.max(Timestamp)], keyby = .(Interval = ceiling_date(Timestamp, "15 min"))]
编辑: 对于其他数据集(无截短的秒数),我们得到
df0[, .SD[.N], by = .(Interval = ceiling_date(Timestamp, "15 min"))]
1: 2018-08-12 23:15:00 51 2: 2018-08-13 00:15:00 55 3: 2018-08-13 00:30:00 57 4: 2018-08-13 00:45:00 60 5: 2018-08-13 01:00:00 61 6: 2018-08-13 01:15:00 62
请注意,这些值将在不缩短秒数的情况下移动到下一个间隔。
step <- "15 min"
df[, .SD[.N], by = .(Interval = ceiling_date(Timestamp, step))][
.(seq(min(Interval), max(Interval), step)), on = .(Interval = V1)]
在这里,我们加入一系列时间戳以完成缺少的间隔:
Interval Value..kW. 1: 2018-08-12 23:00:00 51 2: 2018-08-12 23:15:00 NA 3: 2018-08-12 23:30:00 NA 4: 2018-08-12 23:45:00 NA 5: 2018-08-13 00:00:00 52 6: 2018-08-13 00:15:00 55 7: 2018-08-13 00:30:00 57 8: 2018-08-13 00:45:00 60 9: 2018-08-13 01:00:00 61 10: 2018-08-13 01:15:00 62
现在,通过NA
值,差距在结果中变得可见。
编辑: 对于其他数据集(无截短的秒数),我们得到
df0[, .SD[.N], by = .(Interval = ceiling_date(Timestamp, step))][
.(seq(min(Interval), max(Interval), step)), on = .(Interval = V1)]
Interval Value..kW. 1: 2018-08-12 23:15:00 51 2: 2018-08-12 23:30:00 NA 3: 2018-08-12 23:45:00 NA 4: 2018-08-13 00:00:00 NA 5: 2018-08-13 00:15:00 55 6: 2018-08-13 00:30:00 57 7: 2018-08-13 00:45:00 60 8: 2018-08-13 01:00:00 61 9: 2018-08-13 01:15:00 62
这是Matt's approach的精简版本
step = "15 min"
df[.(seq(floor_date(min(Timestamp), step), ceiling_date(max(Timestamp), step),by = step)),
on = .(Timestamp = V1), roll = TRUE]
Timestamp Value..kW. 1: 2018-08-12 23:00:00 51 2: 2018-08-12 23:15:00 51 3: 2018-08-12 23:30:00 51 4: 2018-08-12 23:45:00 51 5: 2018-08-13 00:00:00 52 6: 2018-08-13 00:15:00 55 7: 2018-08-13 00:30:00 57 8: 2018-08-13 00:45:00 60 9: 2018-08-13 01:00:00 61 10: 2018-08-13 01:15:00 62
在此处,间隙填充有从最新可用值复制的数据。从结果看,不再可见输入数据中存在间隙。
编辑: 对于其他数据集(无截短的秒数),我们得到
df0[.(seq(floor_date(min(Timestamp), step), ceiling_date(max(Timestamp), step),by = step)),
on = .(Timestamp = V1), roll = TRUE]
Timestamp Value..kW. 1: 2018-08-12 23:00:00 NA 2: 2018-08-12 23:15:00 51 3: 2018-08-12 23:30:00 51 4: 2018-08-12 23:45:00 51 5: 2018-08-13 00:00:00 51 6: 2018-08-13 00:15:00 55 7: 2018-08-13 00:30:00 57 8: 2018-08-13 00:45:00 60 9: 2018-08-13 01:00:00 61 10: 2018-08-13 01:15:00 62
在这里,第一行有一个未填补的空白。这是由间隔序列的构造方式引起的。可以避免稍加修改
df0[.(seq(ceiling_date(min(Timestamp), step), ceiling_date(max(Timestamp), step),by = step)),
on = .(Timestamp = V1), roll = TRUE]
Timestamp Value..kW.
1: 2018-08-12 23:15:00 51
2: 2018-08-12 23:30:00 51
3: 2018-08-12 23:45:00 51
4: 2018-08-13 00:00:00 51
5: 2018-08-13 00:15:00 55
6: 2018-08-13 00:30:00 57
7: 2018-08-13 00:45:00 60
8: 2018-08-13 01:00:00 61
9: 2018-08-13 01:15:00 62
该OP提供的数据为dput()
df <-
structure(list(Timestamp = c("8/12/2018 23:00:00", "8/13/2018 0:00:00",
"8/13/2018 0:10:00", "8/13/2018 0:14:00", "8/13/2018 0:15:00",
"8/13/2018 0:19:00", "8/13/2018 0:29:00", "8/13/2018 0:38:00",
"8/13/2018 0:44:00", "8/13/2018 0:45:00", "8/13/2018 0:58:00",
"8/13/2018 1:01:00"), Value..kW. = 51:62), .Names = c("Timestamp",
"Value..kW."), class = "data.frame", row.names = c(NA, -12L))
编辑: :OP提供了两个略有不同的数据集:
dput()
,其中秒被截断(此答案中的df
)df
中打印df0
(此答案中的df0 <- data.frame(
readr::read_table(" Timestamp Value.(kW)
8/12/2018 23:00:06 51
8/13/2018 0:00:16 52
8/13/2018 0:10:26 53
8/13/2018 0:14:36 54
8/13/2018 0:15:00 55
8/13/2018 0:19:57 56
8/13/2018 0:29:09 57
8/13/2018 0:38:17 58
8/13/2018 0:44:59 59
8/13/2018 0:45:00 60
8/13/2018 0:58:47 61
8/13/2018 1:01:57 62
"))
# prepare
library(lubridate)
library(data.table)
setDT(df0)[, Timestamp := mdy_hms(Timestamp)]
)这种细微的差异会影响结果。因此,这是打印出来的数据集:
./gradlew :nameOfModule:action