【问题标题】:How to speed up the simulation when processing time and date处理时间和日期时如何加快模拟速度
【发布时间】:2015-01-18 13:11:11
【问题描述】:

我正在尝试在 R 中编写一种预测方法。预测变量是天气变量以及滞后测量的功率值。数据的准确性为一分钟,并提供相应的时间和日期。 为了将功率的滞后值添加到预测变量列表中,我的目标是考虑最后十分钟的值。如果我确定数据库是完美的并且全年所有分钟的值都可用,我可以简单地移动 Power 列,但可能并非总是如此,我每次 t 都使用以下代码来检查是否所有相应的十分钟滞后值都可用,并将它们提取并存储在矩阵中。问题是,该过程非常耗时,并且需要很长时间来模拟。在这里,我给出了可重现的例子。 我试图将 as.POSIXlt 更改为 as.POSIXct 模拟时间变得更好但没有那么多。我还尝试将 data.frame 更改为矩阵(使用 as.matrix),但它将 POSIXct 值转换为“字符”类。 我想知道你们中的任何人都可以提出更好的方法。谢谢。

rm(list = ls())
cat("\014")

st="2012/01/01"
et="2012/02/27"

st <- as.POSIXlt(as.Date(st))
et <- as.POSIXlt(as.Date(et))
time= seq(from=st, to=et,by=60)
time<as.POSIXlt(time)
#Window is the number of lag values
#leadTime is look-ahead time (forecast horizon)
leadTime=10;
Window=15;

zzzz=time[1:8000]
Total_Zone1=abind(matrix(rnorm(4000*2),4000*2,1), matrix(rnorm(4000*2),4000*2,1), matrix(rnorm(4000*2),4000*2,1),time[1:8000])
N_Train=nrow(Total_Zone1);
lag_Power=matrix(0,N_Train,Window)
colnames(Total_Zone1) <- c( "airtemp","humidity",  "Power", "time")
Total_Zone1<- as.data.frame(Total_Zone1)
for (tt in 4000:N_Train){
  Statlag=Total_Zone1$time[tt]-(leadTime+Window)*60
  EndLag=Total_Zone1$time[tt]-(leadTime)*60
  Index_lags=which((Total_Zone1$time>Statlag)&(Total_Zone1$time<=EndLag))
  if (size(Index_lags)[2]<Window) {
    Statlag2=Total_Zone1$time[tt]-24*60*60
    Index_lags2=which(Total_Zone1$time==Statlag2)
    tem1=rep(Total_Zone1[Index_lags2,c("Power")],Window-size(Index_lags)[2])
    lag_Power[tt,]=t(c(Total_Zone1[Index_lags,c("Power")],tem1))
  }else{
     lag_Power[tt,]=t(Total_Zone1[Index_lags,c("Power")])
  }
}

【问题讨论】:

  • size() 函数是什么?我以前从未见过,而且我的 R 中似乎没有它 (Error: could not find function "size")。
  • 它类似于 Matlab 中的 size() 和 R 中的“dim”。我不记得它所属的包。为了安全起见,最好使用“dim”或“length” :)

标签: r


【解决方案1】:

我建议的第一件事是将填写缺失数据的任务与重新格式化数据的任务分开。您已经在 for 循环中组合了这两个任务,但我认为通过这种分离可以简化和加速代码。

为了演示,我将使用我自己的简化示例代码和数据,这与您的类似。以下演示使用一个小时的时间点,从 2012-01-01 09:00 到 2012-01-01 09:59。我已经生成了前 20 分钟的完整数据,并模拟了剩余 40 分钟的缺失数据:

timeFirst20Min <- seq(as.POSIXct('2012-01-01 09:00'),as.POSIXct('2012-01-01 09:19'),60);
timeNextScattered10 <- sort(sample(seq(as.POSIXct('2012-01-01 09:20'),as.POSIXct('2012-01-01 09:59'),60),10));
timeRaw <- c(timeFirst20Min,timeNextScattered10);

raw <- data.frame(airtemp=rnorm(30), humidity=rnorm(30), power=rnorm(30), time=timeRaw );

timeFull <- seq(as.POSIXct('2012-01-01 09:00'),as.POSIXct('2012-01-01 09:59'),60);

clean <- merge(raw, data.frame(time=timeFull), all=T );

clean;

这会产生以下输出:

                  time     airtemp    humidity       power
1  2012-01-01 09:00:00 -1.84406568 -1.51751811 -0.09391613
2  2012-01-01 09:01:00 -0.58830616 -0.02222524 -0.07865711
3  2012-01-01 09:02:00  1.63189916 -1.35274437 -1.32762005
4  2012-01-01 09:03:00 -1.96424678  0.07326323 -0.29004060
5  2012-01-01 09:04:00 -0.60856223  1.15876062  0.29804843
6  2012-01-01 09:05:00 -0.11504175 -0.43092259  0.49660688
7  2012-01-01 09:06:00  0.24671752  0.58974028 -1.08949827
8  2012-01-01 09:07:00  0.88375964  0.35821875 -0.94881659
9  2012-01-01 09:08:00 -0.70284907 -2.39016066  0.03804497
10 2012-01-01 09:09:00  1.34738493  0.64676077  0.77714355
11 2012-01-01 09:10:00  0.32271920  1.83127669 -1.44754595
12 2012-01-01 09:11:00 -0.46106830 -1.82204149  1.28886422
13 2012-01-01 09:12:00  2.27484699 -1.29816051  0.67963614
14 2012-01-01 09:13:00 -0.25799515 -0.23864259  0.33414247
15 2012-01-01 09:14:00  0.27535436  1.15491712  1.25857697
16 2012-01-01 09:15:00  0.09447671  0.72562227  0.35426141
17 2012-01-01 09:16:00  2.46141564  0.10448464 -0.04715810
18 2012-01-01 09:17:00  0.32952643 -0.51843045 -0.44380916
19 2012-01-01 09:18:00  0.34571678  1.74200137  2.05858658
20 2012-01-01 09:19:00  0.62863598 -0.38642998  1.29170691
21 2012-01-01 09:20:00          NA          NA          NA
22 2012-01-01 09:21:00          NA          NA          NA
23 2012-01-01 09:22:00  0.83148733 -0.79160256 -0.98798400
24 2012-01-01 09:23:00          NA          NA          NA
25 2012-01-01 09:24:00          NA          NA          NA
26 2012-01-01 09:25:00          NA          NA          NA
27 2012-01-01 09:26:00 -0.80548958  0.99318673  0.49630420
28 2012-01-01 09:27:00          NA          NA          NA
29 2012-01-01 09:28:00 -1.12821534 -0.64763280  0.28033445
30 2012-01-01 09:29:00          NA          NA          NA
31 2012-01-01 09:30:00  1.77407448  0.21064525  0.97942804
32 2012-01-01 09:31:00          NA          NA          NA
33 2012-01-01 09:32:00 -0.71832822  0.89608884 -0.14460970
34 2012-01-01 09:33:00          NA          NA          NA
35 2012-01-01 09:34:00          NA          NA          NA
36 2012-01-01 09:35:00          NA          NA          NA
37 2012-01-01 09:36:00          NA          NA          NA
38 2012-01-01 09:37:00          NA          NA          NA
39 2012-01-01 09:38:00          NA          NA          NA
40 2012-01-01 09:39:00 -0.17353680  1.69963228  0.10863195
41 2012-01-01 09:40:00  1.03484529  1.69734966  3.00898820
42 2012-01-01 09:41:00          NA          NA          NA
43 2012-01-01 09:42:00          NA          NA          NA
44 2012-01-01 09:43:00 -1.13983790  1.51982921  0.58583242
45 2012-01-01 09:44:00          NA          NA          NA
46 2012-01-01 09:45:00          NA          NA          NA
47 2012-01-01 09:46:00          NA          NA          NA
48 2012-01-01 09:47:00          NA          NA          NA
49 2012-01-01 09:48:00          NA          NA          NA
50 2012-01-01 09:49:00          NA          NA          NA
51 2012-01-01 09:50:00          NA          NA          NA
52 2012-01-01 09:51:00          NA          NA          NA
53 2012-01-01 09:52:00 -0.93153818  0.77736403  2.08962697
54 2012-01-01 09:53:00          NA          NA          NA
55 2012-01-01 09:54:00  2.26031675 -0.49847630 -1.48191078
56 2012-01-01 09:55:00          NA          NA          NA
57 2012-01-01 09:56:00          NA          NA          NA
58 2012-01-01 09:57:00          NA          NA          NA
59 2012-01-01 09:58:00          NA          NA          NA
60 2012-01-01 09:59:00          NA          NA          NA

所以第一个任务是在clean 上插入缺失的幂值。现在,在您的代码中,您似乎正在向后看整整 24 小时,以获取在基准时间点之前恰好存在的功率值(如果存在;它不能保证存在,是吗?) ,并将其复制到向量的末尾,该向量表示在窗口期间进行的功率测量。这是我指的代码:

Statlag2=Total_Zone1$time[tt]-24*60*60
Index_lags2=which(Total_Zone1$time==Statlag2)
tem1=rep(Total_Zone1[Index_lags2,c("Power")],Window-size(Index_lags)[2])
lag_Power[tt,]=t(c(Total_Zone1[Index_lags,c("Power")],tem1))

我不确定您为什么要向后看 24 小时,尤其是考虑到窗口只有 15 分钟并且仅在基准时间点前 10 分钟结束。我也不确定为什么您将插值值(充分复制以弥补可用功率值的不足)添加到存储在lag_Power 上的行的 end 上;不应该是开始吗,特别是考虑到插值来自窗口之前这么长时间?我可能在这里遗漏了重要的背景;如果我遗漏了什么,请发表评论。

无论如何,我要做的就是及时从最近的可用值中填充缺失的功率值。我发现了一个出色的最近插值函数,它可以直接处理来自Replacing NAs in R with nearest value 的单个向量。在这里,我自己重新格式化:

interpolateMissing <- function(dat) {

    N <- length(dat);
    missing <- which(is.na(dat));
    if (length(missing) %in% c(0,N)) return(dat);

    notMissing <- which(!is.na(dat));
    intervals <- findInterval(missing, notMissing, all.inside=T );

    leftPos <- notMissing[pmax(1,intervals)];
    rightPos <- notMissing[pmin(N,intervals+1)];
    leftDist <- missing - leftPos;
    rightDist <- rightPos - missing;

    dat[missing] <- ifelse(leftDist <= rightDist, dat[leftPos], dat[rightPos] );

    return(dat);

};

您可以使用它轻松地从最接近的可用值插入所有缺失的功率值:

clean$power <- interpolateMissing(clean$power);

clean 现在看起来像这样:

                  time     airtemp    humidity       power
1  2012-01-01 09:00:00 -1.84406568 -1.51751811 -0.09391613
2  2012-01-01 09:01:00 -0.58830616 -0.02222524 -0.07865711
3  2012-01-01 09:02:00  1.63189916 -1.35274437 -1.32762005
4  2012-01-01 09:03:00 -1.96424678  0.07326323 -0.29004060
5  2012-01-01 09:04:00 -0.60856223  1.15876062  0.29804843
6  2012-01-01 09:05:00 -0.11504175 -0.43092259  0.49660688
7  2012-01-01 09:06:00  0.24671752  0.58974028 -1.08949827
8  2012-01-01 09:07:00  0.88375964  0.35821875 -0.94881659
9  2012-01-01 09:08:00 -0.70284907 -2.39016066  0.03804497
10 2012-01-01 09:09:00  1.34738493  0.64676077  0.77714355
11 2012-01-01 09:10:00  0.32271920  1.83127669 -1.44754595
12 2012-01-01 09:11:00 -0.46106830 -1.82204149  1.28886422
13 2012-01-01 09:12:00  2.27484699 -1.29816051  0.67963614
14 2012-01-01 09:13:00 -0.25799515 -0.23864259  0.33414247
15 2012-01-01 09:14:00  0.27535436  1.15491712  1.25857697
16 2012-01-01 09:15:00  0.09447671  0.72562227  0.35426141
17 2012-01-01 09:16:00  2.46141564  0.10448464 -0.04715810
18 2012-01-01 09:17:00  0.32952643 -0.51843045 -0.44380916
19 2012-01-01 09:18:00  0.34571678  1.74200137  2.05858658
20 2012-01-01 09:19:00  0.62863598 -0.38642998  1.29170691
21 2012-01-01 09:20:00          NA          NA  1.29170691
22 2012-01-01 09:21:00          NA          NA -0.98798400
23 2012-01-01 09:22:00  0.83148733 -0.79160256 -0.98798400
24 2012-01-01 09:23:00          NA          NA -0.98798400
25 2012-01-01 09:24:00          NA          NA -0.98798400
26 2012-01-01 09:25:00          NA          NA  0.49630420
27 2012-01-01 09:26:00 -0.80548958  0.99318673  0.49630420
28 2012-01-01 09:27:00          NA          NA  0.49630420
29 2012-01-01 09:28:00 -1.12821534 -0.64763280  0.28033445
30 2012-01-01 09:29:00          NA          NA  0.28033445
31 2012-01-01 09:30:00  1.77407448  0.21064525  0.97942804
32 2012-01-01 09:31:00          NA          NA  0.97942804
33 2012-01-01 09:32:00 -0.71832822  0.89608884 -0.14460970
34 2012-01-01 09:33:00          NA          NA -0.14460970
35 2012-01-01 09:34:00          NA          NA -0.14460970
36 2012-01-01 09:35:00          NA          NA -0.14460970
37 2012-01-01 09:36:00          NA          NA  0.10863195
38 2012-01-01 09:37:00          NA          NA  0.10863195
39 2012-01-01 09:38:00          NA          NA  0.10863195
40 2012-01-01 09:39:00 -0.17353680  1.69963228  0.10863195
41 2012-01-01 09:40:00  1.03484529  1.69734966  3.00898820
42 2012-01-01 09:41:00          NA          NA  3.00898820
43 2012-01-01 09:42:00          NA          NA  0.58583242
44 2012-01-01 09:43:00 -1.13983790  1.51982921  0.58583242
45 2012-01-01 09:44:00          NA          NA  0.58583242
46 2012-01-01 09:45:00          NA          NA  0.58583242
47 2012-01-01 09:46:00          NA          NA  0.58583242
48 2012-01-01 09:47:00          NA          NA  0.58583242
49 2012-01-01 09:48:00          NA          NA  2.08962697
50 2012-01-01 09:49:00          NA          NA  2.08962697
51 2012-01-01 09:50:00          NA          NA  2.08962697
52 2012-01-01 09:51:00          NA          NA  2.08962697
53 2012-01-01 09:52:00 -0.93153818  0.77736403  2.08962697
54 2012-01-01 09:53:00          NA          NA  2.08962697
55 2012-01-01 09:54:00  2.26031675 -0.49847630 -1.48191078
56 2012-01-01 09:55:00          NA          NA -1.48191078
57 2012-01-01 09:56:00          NA          NA -1.48191078
58 2012-01-01 09:57:00          NA          NA -1.48191078
59 2012-01-01 09:58:00          NA          NA -1.48191078
60 2012-01-01 09:59:00          NA          NA -1.48191078

所以,现在可以使用了,无需担心缺失值。

最后一点是,我不确定构造lag_Power 矩阵有什么好处。每个窗口与其他窗口有很大重叠,因此该矩阵将包含大量重复数据。相反,我会看看这些数据是如何在这个预备代码的下游使用的,看看是否可以更改它以直接在clean(或您的代码Total_Zone1)中访问特定于窗口的值。这可以节省处理时间和内存影响。

【讨论】:

  • 谢谢一百万。我的数据库包含从早上 5 点到晚上 7 点的测量值。假设预测提前期为 10 分钟,我计划使用“window=15”数据作为预测变量。因此,对于上午 5:25 的 PV 预测,我将使用上午 5:00 到 5:15 的存档值。为了在早上 5:25 之前执行预测,因为没有可用的滞后数据的窗口数,我决定使用关注前一天的测量值以及 for 循环中复制功能的工作
  • 还有一件事是,如果某些时间的测量值不可用,在我的数据库中,它们不会由 Na 值显示,相反它们对应的行包括数据和时间等没有给出值。我的意思是,例如在数据库中,数据可能会从上午 9:12 跳转到上午 9:15(而常规步骤是一分钟)
  • 是的,我明白,这很有意义。关于您的第二条评论,我的示例代码显示了如何将完整的时间序列与缺少行的原始数据合并,如您所描述的。 merge() 函数(重要的是all=T)基本上添加了那些缺失的行,NA 用于缺失值,所以我认为这非常适合您的目的。在插值步骤之后,您最终会得到一个干净的表,没有丢失的行和丢失的值。希望对您有所帮助!
【解决方案2】:

data.table 包中的 rolling merge 在这里应该可以正常工作:

#Bring in data.table package
library(data.table)
setDT(Total_Zone1) #Convert data to data.table
leadTime=10
Window=15
Total_Zone1[, time2 := time-60*(leadTime)]

#Create lag table
Lag_Table <- Total_Zone1[,.(time,Lag.Power=Power)]

#Set keys and perform rolling merge
setkey(Total_Zone1,time2)
setkey(Lag_Table,time)

#Perform rolling merge in data.table
Result <- Lag_Table[Total_Zone1,roll=+(Window*60)]

结果:

Result[1:15]

          time   Lag.Power    airtemp   humidity       Power     i.time
 1: 1325375400          NA  0.5341823  0.6114278  0.01378526 1325376000
 2: 1325375460          NA -0.4063909  1.0928144 -0.63712941 1325376060
 3: 1325375520          NA -1.3841581 -0.6204582  0.80553870 1325376120
 4: 1325375580          NA  1.5146208 -0.4343324 -1.29370219 1325376180
 5: 1325375640          NA -1.4949108  0.1416236 -0.64836292 1325376240
 6: 1325375700          NA -1.7832364 -1.2018948 -1.13257989 1325376300
 7: 1325375760          NA -1.2111490  0.5819049  0.22450291 1325376360
 8: 1325375820          NA -0.2837945  0.3196630  0.43199908 1325376420
 9: 1325375880          NA -1.2773624  0.3724754 -1.31807585 1325376480
10: 1325375940          NA  0.7710507 -1.0114118 -0.85951358 1325376540
11: 1325376000  0.01378526  0.7983597  1.7683065  0.38032568 1325376600
12: 1325376060 -0.63712941  0.3813563 -0.3905894  1.47871752 1325376660
13: 1325376120  0.80553870  0.7421624 -1.2265799  0.34509387 1325376720
14: 1325376180 -1.29370219  0.7768929 -1.2244243 -0.02769379 1325376780
15: 1325376240 -0.64836292 -0.8311352  0.8486815  0.16926006 1325376840

【讨论】:

  • 谢谢迈克。你的评论很有帮助。基本上我需要使用滞后数据窗口。例如,要预测早上 8 点的功率,我需要使用早上 7:35 到早上 7:50 的数据(提前期 = 10 分钟,窗口 = 15 分钟,分辨率为分钟)。我如何在不使用 for 循环的情况下设法执行它。非常感谢。
  • 啊..我想我明白了。我稍微改了一下。
猜你喜欢
  • 1970-01-01
  • 2016-11-06
  • 2018-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-24
相关资源
最近更新 更多