ich mit der Feststellung beginnen, werden feststellen, dass In Ihrer for-Schleife ist ein Fehler vorhanden. Anstelle von n*24*80
hast du wahrscheinlich (n+80)*24
gemeint. Der Zähler in Ihrer Schleife sollte auch von 0 bis 99 anstelle von 1 bis 100 gehen, wenn Sie auch die Vorhersage für den 81. Tag einbeziehen möchten.
Ich werde versuchen, eine elegante Lösung für Ihr Problem unten zu bieten. Zunächst definieren wir unsere Testdatenrahmen in genau der gleichen Art und Weise, die Sie in Ihrem Beitrag geleistet haben:
set.seed(2)
df <- data.frame(
Date = seq.POSIXt(from = as.POSIXct("2015-01-01 00:00:00"),
to = as.POSIXct("2015-06-30 00:00:00"), by = "hour"))
df <- df %>% mutate(Hour = as.numeric(format(Date, "%H")) + 1,
Wind = runif(4320, min = 1, max = 5000),
Temp = runif(4320, min = - 20, max = 25),
Price = runif(4320, min = -15, max = 45)
)
Als nächstes definieren wir eine Funktion, die die Vorhersage für einen bestimmten Tag durchführt. Eingabeargumente sind der betrachtete Datenrahmen und die minimale Anzahl an Trainingstagen, die im Trainingset sein sollten (= 80 in diesem Beispiel). minTrainingDays+offSet+1
repräsentiert den tatsächlichen Tag, den wir vorhersagen. Beachten Sie, dass wir beginnen, für den Offset von 0 zu zählen.
forecastOneDay <- function(theData,minTrainingDays,offset)
{
nrTrainingRows <- (minTrainingDays+offset)*24
theForecast <- theData %>%
filter(min_rank(Date) <= nrTrainingRows+24) %>% # Drop future data that we don't need
group_by(Hour) %>%
do ({
trainingData <- head(.,-1) # For each group, drop the last entry from the dataframe
forecastData <- tail(.,1) %>% select(Date,Hour,Wind,Temp) # For each group, predict the last entry
fit <- Arima(trainingData$Price, xreg=trainingData[,3:4], order=c(1,1,0))
data.frame(forecastData, realPrice = tail(.,1)$Price, predictedPrice = forecast.Arima(fit,xreg=forecastData[3:4])$mean)
})
}
Wir wollen Tage 81-180 voraussagen. Mit anderen Worten, wir benötigen mindestens 80 Tage in unserem Trainingssatz und möchten die Funktionsergebnisse für Offsets 0:99
berechnen. Dies kann mit einem einfachen lapply
Aufruf erreicht werden. Wir beenden, indem Sie alle Ergebnisse zusammen in einem Datenrahmen verschmelzen:
# Perform one day forecasts for days 81-180
resultList <- lapply(0:99, function(x) forecastOneDay(df,80,x))
# Merge all the results
mergedForecasts <- do.call("rbind",resultList)
EDIT Nach Ihrem Beitrag zu überprüfen und eine andere Antwort, die in der Zwischenzeit geschrieben wurde ich mit meiner Antwort zwei mögliche Probleme bemerkt. Zuerst wollten Sie ein rollendes Fenster von 80 Tagen Trainingsdaten. In meinem vorherigen Code werden jedoch alle verfügbaren Trainingsdaten verwendet, um das Modell anzupassen, anstatt nur 80 Tage zurückzugehen. Zweitens ist der Code nicht robust gegenüber Änderungen der Sommerzeit.
Diese beiden Probleme sind im folgenden Code behoben.Die Eingaben der Funktion sind jetzt auch intuitiver: Die Anzahl der Trainingstage und der tatsächliche vorhergesagte Tag können als Eingabeargumente verwendet werden. Beachten Sie, dass das Datenformat POSIXlt
Dinge wie Sommerzeit, Schaltjahre usw. bei der Durchführung von Datenoperationen korrekt verarbeitet. Da die Daten in Ihrem Datenrahmen vom Typ POSIXct
sind, müssen wir eine kleine Typumwandlung hin und her machen, um die Dinge richtig zu handhaben.
Neuer Code unten:
forecastOneDay <- function(theData,nrTrainingDays,predictDay) # predictDay should be greater than nrTrainingDays
{
initialDate <- as.POSIXlt(theData$Date[1]); # First day (midnight hour)
startDate <- initialDate # Beginning of training interval
endDate <- initialDate # End of test interval
startDate$mday <- initialDate$mday + (predictDay-nrTrainingDays-1) # Go back 80 days from predictday
endDate$mday <- startDate$mday + (nrTrainingDays+1) # +1 to include prediction day
theForecast <- theData %>%
filter(Date >= as.POSIXct(startDate),Date < as.POSIXct(endDate)) %>%
group_by(Hour) %>%
do ({
trainingData <- head(.,-1) # For each group, drop the last entry from the dataframe
forecastData <- tail(.,1) %>% select(Date,Hour,Wind,Temp) # For each group, predict the last entry
fit <- Arima(trainingData$Price, xreg=trainingData[,3:4], order=c(1,1,0))
data.frame(forecastData, realPrice = tail(.,1)$Price, predictedPrice = forecast.Arima(fit,xreg=forecastData[3:4])$mean)
})
}
# Perform one day forecasts for days 81-180
resultList <- lapply(81:180, function(x) forecastOneDay(df,80,x))
# Merge all the results
mergedForecasts <- do.call("rbind",resultList)
Ergebnisse wie folgt aussehen:
> head(mergedForecasts)
Source: local data frame [6 x 6]
Groups: Hour
Date Hour Wind Temp realPrice predictedPrice
1 2015-03-22 00:00:00 1 1691.589 -8.722152 -11.207139 5.918541
2 2015-03-22 01:00:00 2 1790.928 18.098358 3.902686 37.885532
3 2015-03-22 02:00:00 3 1457.195 10.166422 22.193270 34.984164
4 2015-03-22 03:00:00 4 1414.502 4.993783 6.370435 12.037642
5 2015-03-22 04:00:00 5 3020.755 9.540715 25.440357 -1.030102
6 2015-03-22 05:00:00 6 4102.651 2.446729 33.528199 39.607848
> tail(mergedForecasts)
Source: local data frame [6 x 6]
Groups: Hour
Date Hour Wind Temp realPrice predictedPrice
1 2015-06-29 18:00:00 19 1521.9609 13.6414797 12.884175 -6.7789109
2 2015-06-29 19:00:00 20 555.1534 3.4758159 37.958768 -5.1193514
3 2015-06-29 20:00:00 21 4337.6605 4.7242352 -9.244882 33.6817379
4 2015-06-29 21:00:00 22 3140.1531 0.8127839 15.825230 -0.4625457
5 2015-06-29 22:00:00 23 1389.0330 20.4667234 -14.802268 15.6755880
6 2015-06-29 23:00:00 24 763.0704 9.1646139 23.407525 3.8214642
Zu lange Frage? – NoThanks