R:如何找到数据点重叠且无缺失数据的最长周期?
我有一个非常大的变电站电力负荷时间序列数据集,该数据集经过清理,具有15分钟的一致时间间隔,但仍有大量数据丢失。变电站分为单独的馈线,其形式如下:R:如何找到数据点重叠且无缺失数据的最长周期?,r,datetime,missing-data,overlap,overlapping,R,Datetime,Missing Data,Overlap,Overlapping,我有一个非常大的变电站电力负荷时间序列数据集,该数据集经过清理,具有15分钟的一致时间间隔,但仍有大量数据丢失。变电站分为单独的馈线,其形式如下: Feeder <- c("F1","F1","F1","F1","F1", "F2","F2","F2","F2","F2", "F3&
Feeder <- c("F1","F1","F1","F1","F1", "F2","F2","F2","F2","F2", "F3","F3","F3","F3","F3")
Load <- c(3.1, NA, 4.0, 3.8, 3.6, 2.1, NA, 2.6, 2.9, 3.0, 2.4, NA, 2.3, 2.2, 2.5)
start <- as.POSIXct("2016-01-12 23:15:00")
end <- as.POSIXct("2016-01-13 00:15:00")
DateTimeseq <- seq(start, end, by = "15 min")
DateTime <- c(DateTimeseq, DateTimeseq, DateTimeseq)
dt <- data.frame(Feeder, Load, DateTime)
我的实际数据跨越数年,但我已将其压缩,因此很容易复制。如您所见,缺少一些值。我的实际数据集有大量缺失数据。为了进行有效的分析,我需要找到所有馈线没有缺失负载数据点的周期,即最长的重叠周期。如果可能的话,我想生成一个最长重叠周期的列表,没有任何NA值,最小值约为24小时。我知道,对于我给出的示例,这是不可能的,但如果你能告诉我这将是多么棒!。在本例中,您可以使用至少15分钟的时间
从简单数据中可以看出,2016-01-12 23:45:00和2016-01-13 00:15:00之间的最长时间为30分钟。然而,在本例中,第二个最长周期为15分钟,但在最长周期内。如果可能的话,我想运行它,这样它就不会复制值。如果是这样的话,在这种情况下,第二长时间将是2016-01-12 23:15:00的重叠点
您可以随意使用它,如果它能让您更轻松的话,您可以添加更多的价值。为不同的馈线创建单独的列可能是有益的。我通常使用dplyr中的管道,但这不是必需的。如果您需要更多信息,请随时询问
谢谢 也许,这会给你一个开始。对于每个馈线,您可以在NA值之间创建组,计算其第一个和最后一个值,并在它们之间创建15分钟的序列。然后可以计算数据中出现最多的时间间隔
library(dplyr)
dt %>%
group_by(Feeder) %>%
group_by(grp = cumsum(is.na(Load)), .add = TRUE) %>%
#Use add = TRUE in old dplyr
#group_by(grp = cumsum(is.na(Load)), add = TRUE) %>%
summarise(start = first(DateTime),
end = last(DateTime)) %>%
ungroup %>%
mutate(datetime = purrr::map2(start, end, seq, by = '15 mins')) %>%
tidyr::unnest(datetime) %>%
select(-start, -end) %>%
count(datetime, sort = TRUE)
基本R解决方案:
# Strategy 1 contiguous period classification:
data.frame(do.call("rbind", lapply(split(dt, dt$Feeder), function(x){
y <- with(x, x[order(DateTime),])
y$category <- paste0(y$Feeder, ":", cumsum(is.na(y$Load)) + 1)
tmp <- y[!(is.na(y$Load)),]
cat_diff <- do.call("rbind", lapply(split(tmp, tmp$category),
function(z){
data.frame(category = unique(z$category),
max_diff = difftime(max(z$DateTime),
min(z$DateTime),
units = "hours"))}))
y$max_diff <- cat_diff$max_diff[match(y$category, cat_diff$category)]
return(y)
}
)
), row.names = NULL
)
下面是另一个用于强制转换到宽表并检查连续行(无任何NAs)的选项:
library(data.table)
wDT <- dcast(setDT(dt)[, na := +is.na(Load)], DateTime ~ Feeder, value.var="na")
wDT[, c("ri", "rr") := {
ri <- rleid(rowSums(.SD)==0L)
.(ri, rowid(ri))
}, .SDcols=names(wDT)[-1L]]
range(wDT[ri %in% ri[rr==max(rr)]]$DateTime)
#[1] "2016-01-12 23:45:00 +08" "2016-01-13 00:15:00 +08"
我可能会为您提供一个很好的3行代码解决方案: 首先,将数据转换为宽格式,即每个馈线都是一列 检查行(现在是时间戳)是否所有馈线均为非NA。这给出了12:15正确,12:30正确,12:45错误,。。。此上下文中的FALSE表示所有馈线都可用于此时间戳 对生成的True、True、False、False…执行运行长度编码,。。。序列-这允许查找您称之为连续重叠的时段 代码: 意思是在开始时,一行有1个False,下一行有1个TRUE,下一行有3个False 您现在可以轻松地处理此结果。您可能希望过滤掉真实的运行,因为您只查找最长的运行,其中所有数据都可用—这些是错误的运行。 然后,您可以查找最大跑步次数,也可以查找如跑步次数>4次,即15分钟数据的1小时 Ellis问题的附加代码
这将为您提供一个data.frame,按连续非NA段的持续时间以及开始和结束时间排序。这对每个馈线都很有效,但我需要找到一个周期,当所有馈线都没有NA值时。即所有馈线的重叠期。这样我就可以选择一个日期,在这个日期里,我可以分析每个馈线,使我的研究更有效。@EllisR8检查答案中的更新,看看是否有帮助。这将为您提供最频繁出现的15分钟间隔。错误:输入日期时间发生变化。x‘from’必须是有限数ℹ 输入日期时间为purrr::map2start,end,seq,by=15分钟。您的数据中可能有NA值,但在共享的示例中没有显示。您不必共享整个数据集。您需要使您的示例足够完整,以便它能够代表您的实际数据。请注意,我们没有完整的数据集,因此我们不知道其中的哪些小细节可能是导致不工作的原因。我们只能看到您显示的内容。返回错误:data.frame.,do.callrbind,lapplysplitdt,dt$Feeder中的错误::参数表示不同的行数:1294231,21909167Hi,这起作用,但它不显示运行发生的日期时间,以及运行的持续时间。如果可能的话,我想要一个顺序的跑步持续时间的输出,以及跑步的开始和结束日期时间。我想很清楚你可以从那里继续下去。我会补充一些,让你有更好的想法:
library("tidyr")
library("dplyr")
# Into wide format
dt_wide <- dt %>% pivot_wider(names_from = Feeder, values_from = Load)
# Check if complete row is available
dt_anyna <- apply(y,1, anyNA)
# Now we need to find the longest FALSE runs
rle(dt_anyna)
Run Length Encoding
lengths: int [1:3] 1 1 3
values : logi [1:3] FALSE TRUE FALSE
rle <- rle(dt_anyna)
x <- data.frame( value = rle$values, duration = rle$lengths)
x$start <- dt_wide$DateTime[(cumsum(x$duration)- x$duration)+1]
x$end <- dt_wide$DateTime[cumsum(x$duration)]
x$duration_s <- x$end - x$start
ordered <- x[order(x$duration, decreasing = TRUE),]
filtered <- filter(ordered, value == FALSE)
filtered
value duration start end duration_s
FALSE 3 2016-01-12 23:45:00 2016-01-13 00:15:00 1800 secs
FALSE 1 2016-01-12 23:15:00 2016-01-12 23:15:00 0 secs