change axis/scale for time series plot after forecast - r

I'm struggling with changing the x-axis (time) for my time series forecast plot. I have ran many models but I am struggling with the same issue. I'm going to write the code for the model fit, forecast and the plot here for one of the models. First here is my original time series. Note: I'm fitting my model on my training data that is from 2008-2016 and testing my model on my test data for the 11 months in 2017.
Data Split.
sal.ts <- window(sal.ts.original, start=c(2008,1), end=c(2016,12))
sal.test <- window(sal.ts.original, start=c(2017,1))
Now, the model.
sal.hw.mul <- HoltWinters(sal.ts, seasonal = "mult")
sal.hw.mul
fc.hwm <- forecast(sal.hw.mul, h=11)
fc.hwm
plot(fc.hwm, xlim=c(2017,2017+11/12), main = "Forecast from Mutltiplicative HW", xlab = "Year", ylab = "Total Sales, $M")
lines(sal.test,col='red', lwd=2)
legend("topleft", c("Actual", "Predicted"), col = c(4,2), lty = 1)
Here's my forecast plot:
See that ugly 2017.0, 2017.2.... 2017.8? I want it to instead say 1,2,3,....11 for the 11 months of 2017.
Yes, I only want to plot my test data and forecast on it and not the whole series.
I am pretty sure my problem is around my use of the xlim function. I am using that xlim function to just plot the months of 2017 and if I don't use that then R plots the whole series from 2008-2017. I tried to play around with the axis function a lot by setting xaxt="n" in the plot command but still couldn't figure it out.
Let me know if you need more information from me. Any help will be appreciated.
Update, on someone's suggestion I tried to write a custom axis by setting xaxt = 'n' in my plot. Here's the change in code.
x <- seq(1,11,1)
fc.hwm <- forecast(sal.hw.mul, h=11)
fc.hwm
layout(1:1)
plot(fc.hwm, xaxt='n', xlim=c(2017,2017+11/12), main = "Forecast from Mutltiplicative HW", xlab = "Year", ylab = "Total Sales, $M")
axis(side=1, at= x, labels=c("1","2","3","4","5","6","7","8","9","10","11"))
lines(sal.test,col='red', lwd=2)
legend("topleft", c("Actual", "Predicted"), col = c(4,2), lty = 1)
Like you can see. It gets me there half way. I can remove my current axis label but I am not being able to write a new axis. This new code is not even giving me an error or else I would've tried to debug it. It accepts my code but doesn't give me the desired output.

Here's an idea. I'm not sure what the data look like, but I'm guessing that you have a Date type for the date variable -- and that means that your "by" sequence of integer 1 to 11 might be placing those new labels outside the plot limits. Try using a Date sequence instead.
Change this:
x <- seq(1,11,1)
To something like this:
x <- seq.Date(as.Date("2017-01-01"), as.Date("2017-11-01"), "months")
I'm not sure how far into November your data go, so you might want to set that "to" Date in the sequence to December instead, so you can fully cover your November data points.

Related

Changing y axis max in time series R

The ts() object in R doesn't seem to let you use ylim so I'm unable to set a customized y axis range for my time series. If i do use ylim i get a unused variable error. This is what i have for plotting my time series:
dataTimeSeries <- ts(newru$Value, start = c(input$years[1]), end = input$years[2])
plot.ts(dataTimeSeries)
abline(h=amount$toxicityLevels, col="blue") #add horizontal line
I'm trying to add a horizontal line to the time series graph via the abline function, but sometimes the y axis isn't large enough for the line to actually show which is why I'm wondering if theres another way to extend the y axis. Thanks!
Your axis limits are being set in the plot.ts() call. If you want to override the data, set it there, or before there with par().
plotting behavior can be a little unexpected, though, so I can't guarantee it will work without a dput of your data, but here are two options for you to try:
dataTimeSeries <- ts(newru$Value, start = c(input$years[1]), end = input$years[2])
plot.ts(dataTimeSeries, ylim = c(<your min>, <your max>))
abline(h=amount$toxicityLevels, col="blue")
Alternatively
dataTimeSeries <- ts(newru$Value, start = c(input$years[1]), end = input$years[2])
par(ylim = c(<your min>, <your max>)
plot.ts(dataTimeSeries)
abline(h=amount$toxicityLevels, col="blue")

How to plot actual year in x axis of r plot instead of year 0,1,2......20

I am newbie in R. please show me the correct link if I asked my question in wrong forum. I am reading and extracting data from netcdf file. I want to plot actual year i.e. 1980,1981,......1999 in x-axis instead of 0,1,...20. I tried to change the range using xrange or xaxt and axis command in plot but unable to do so.Also, I want to plot the lines between 1980-1999 buthttp://i.stack.imgur.com/z8sEL.png the line continues after 1999 (see image) I tried since last 7 days without any succes and could not concentrate and move on. I have copied partial code and image. I will appreciate your help. Thank you.
for (j in 1:length(station_rchid)){
for (i in 1:length(rchid)){
if(identical(station_rchid[j],rchid[i])){
windows()
per<-'Average Annual '
an_time<-1:nyear
heading <- paste(per,vari,tper,station_name[j])
yrange<- max(varX_year[1,,j],varX_year[2,,j])
plot(an_time,varX_year[1,,j],main=heading,type="l",ylim=c(0,yrange),xlab="Year",ylab=unity,col="red",cex.lab=1.5,cex.axis=1.5)
lines(an_time,varX_year[2,,j],col="blue")
legend("topleft", c("Pred","Obs"),lty=c(1,1),lwd=c(2.5,2.5), col=c("red","blue"),inset = 1.4)
filename<-paste("NZ_Annual_swe_",station_name[i],".xls")
# write.xls(varX_year[ , ,j],file=filename,colNames=TRUE,rowNames=FALSE)
One way is to remove the axes in the plot and then re-add them later. The pretty can help you automate the label placements. Parse all axis-options to the axis lines.
plot(an_time, varX_year, main = heading, type="l", ylim = c(0,yrange)
,xlab = "Year", ylab = unity, col = "red", cex.lab = 1.5,
,axes = FALSE)
axis(1, at = pretty(an_time), labels = pretty(an_time) + 1980, cex.axis=1.5)
axis(2, cex.axis=1.5,)
box()
Be cautious with this approach, since you only change the labels.
Another workaround I suppose could be just to add 1980 to the year vector, i.e.
an_time <- an_time + 1980

plotmeans legends formatting

I am plotting means of grouped data and I'm having trouble getting the legends to be right. The text is so large that one can only see the names of two groups, not all four. I have spent a long time trying to use cex-like commands to change the size, but it doesn't work. I have tried rotating them with las=3, but it doesn't work.
I cannot share the data, but the code is here:
plot.question = function(number){
#which question to plot? get ID
question = names(sorted.by.n)[number]
#the formula
form = paste0("DF.scored.g.scale ~ ",question)
#fit it to data
fit = lm(form, DF.merged.g)
#get ANOVA results
fit.anova = anova(fit)
#get ANOVA p value
p.value = round(fit.anova[[5]][2],4) #p value
#plot it
plotmeans(as.formula(form), DF.merged.g,
ylab = "4 g-items sumscore",
xlab = "Answer",
main = paste0(questions.unique[question,"text"],"\nANOVA p=",p.value),
cex.main = .8,
cex.axis = .8,
cex.lab = .8,
cex.sub = .8,
las=3,) #size of main title
}
Preferably, I'd like to simply make the text smaller, so it can fit. Alternatively, I'd like to rotate it so it can fit (perhaps along with a margin change). If not what else?
One can suppress the legends with xaxt="n", but then one has to add them some other way. Can it really not be done within the plotmeans() function?
Well I tried many things and this was the only thing that worked. Apparently plotmeans() creates a plot that you cannot modify in any way. The only thing I was able to do is to overlay text as a new only-text-plot on top of the plotmeans plot.
myfactor <- factor(rep(c('cat1','cat2','cat3'),20)) #make a factor
mynum <- runif(60) #make a numeric field
plotmeans(mynum ~ myfactor,xaxt='n') #plot them
labs <- paste(names(table(myfactor)), "") #make the names
par(new=T) #create new plot
a<-rev(as.numeric(unique(myfactor))) #count the unique factors to make a vector of their numbers to serve as the positions on the x axis
text(cex=1, x=a, y=0.2, labs, xpd=TRUE, srt=35) #insert the text on the graph.
#here you need to modify y according to your data to find the best place to plot them.
#In my case x=c(1,2,3) because I have 3 categories and y=0.2
#because this is the lowest value of the y axis. The srt argument rotates the text.
You should probably be able to either fix the y axis to have standard values and then use the minimum of that number in the y argument of the text function to make a generic function, or calculate the min value of the y axis each time.
Hope that helps!

R Forecasting with as.POSIXlt/ct

Good day
I read on one of the posts here that "the function forecast::plot.forecast is not designed to be used with axis.Date or axis.POSIXct (which are not used in the package forecast)." This can be seen here:custom axis labels plotting a forecast in R
Nevertheless, they managed to use the forecast package and some code to get the correct axis labels. However, this example is for quarterly data. Also, this example here using 'as.POSIXlt' is for weekly data: Forecasting time series data
I've tried playing with the code but I can't get it to work for monthly data. So my axis labels are still wrong. I'm stumped. Please would you help advise how I get the axis labels to reflect correctly using the forecast package?
Example
library(forecast)
headcount<-c(2475,2468,2452,2464,2500,2548,2536,2565,2590,2608,2625,2663)
date<-c("2013/01/31","2013/02/28","2013/03/31","2013/04/30","2013/05/31","2013/06/30",
"2013/07/31","2013/08/31","2013/09/30","2013/10/31","2013/11/30","2013/12/31")
x<-data.frame(headcount,date)
t<-ts(x$headcount,start=c(2013,1),end=c(2013,12),frequency=12)
fit<-forecast(t,h=12)
plot(forecast(fit))
By doing this, the axis labels come out as 2013.0, 2013.5, 2014.5
I know this is only a year's worth of data. I'm just interested in how to fix the axis labels for monthly data,
Kind regards
D
Here's a possible solution using the links provided
plot(forecast(fit), axes = FALSE)
a <- seq(as.Date(date[1]) + 1, by = "months", length = length(date) + 11)
axis(1, at = as.numeric(a)/365.3 + 1970, labels = format(a, format = "%m/%Y"), cex.axis = 0.9)
axis(2, cex.axis = 0.9)

R X-axis Date Labels using plot()

Using the plot() function in R, I'm trying to produce a scatterplot of points of the form (SaleDate,SalePrice) = (saldt,sapPr) from a time-series, cross-section real estate sales dataset in dataframe format. My problem concerns labels for the X-axis. Just about any series of annual labels would be adequate, e.g. 1999,2000,...,2013 or 1999-01-01,...,2013-01-01. What I'm getting now, a single label, 2000, at what appears to be the proper location won't work.
The following is my call to plot():
plot(r12rgr0$saldt, r12rgr0$salpr/1000, type="p", pch=20, col="blue", cex.axis=.75,
xlim=c(as.Date("1999-01-01"),as.Date("2014-01-01")),
ylim=c(100,650),
main="Heritage Square Sales Prices $000s 1990-2014",xlab="Sale Date",ylab="$000s")
The xlim and ylim are called out to bound the date and price ranges of the data to be plotted; note prices are plotted as $000s. r12rgr0$saldt really is a date; str(r12rgr0$saldt) returns:
Date[1:4190], format: "1999-10-26" "2013-07-06" "2003-08-25" NA NA "2000-05-24" xx
I have reviewed several threads here concerning similar questions, and see that the solution probably lies with turning off the default X-axis behavior and using axis.date, but i) At my current level of R skill, I'm not sure I'd be able to solve the problem, and ii) I wonder why the plotting defaults are producing these rather puzzling (to me, at least) results?
Addl Observations: The Y-axis labels are just fine 100, 200,..., 600. The general appearance of the scatterplot indicates the called-for date ranges are being observed and the relative positions of the plotted points are correct. Replacing xlim=... as above with xlim=c("1999-01-01","2014-01-01")
or
xlim=c(as.numeric(as.character("1999-01-01")),as.numeric(as.character("2014-01-01")))
or
xlim=c(as.POSIXct("1999-01-01", format="%Y-%m-%d"),as.POSIXct("2014-01-01", format="%Y-%m-%d"))
all result in error messages.
With plots it's very hard to reproduce results with out sample data. Here's a sample I'll use
dd<-data.frame(
saldt=seq(as.Date("1999-01-01"), as.Date("2014-01-10"), by="6 mon"),
salpr = cumsum(rnorm(31))
)
A simple plot with
with(dd, plot(saldt, salpr))
produces a few year marks
If i wanted more control, I could use axis.Date as you alluded to
with(dd, plot(saldt, salpr, xaxt="n"))
axis.Date(1, at=seq(min(dd$saldt), max(dd$saldt), by="30 mon"), format="%m-%Y")
which gives
note that xlim will only zoom in parts of the plot. It is not directly connected to the axis labels but the axis labels will adjust to provide a "pretty" range to cover the data that is plotted. Doing just
xlim=c(as.Date("1999-01-01"),as.Date("2014-01-01"))
is the correct way to zoom the plot. No need for conversion to numeric or POSIXct.
If you are running a plot in real time and don't mind some warnings, you can just pass, e.g., format = "%Y-%m-%d" in the plot function. For instance:
plot(seq((Sys.Date()-9),Sys.Date(), 1), runif(10), xlab = "Date", ylab = "Random")
yields:
while:
plot(seq((Sys.Date()-9), Sys.Date(), 1), runif(10), format = "%Y-%m-%d", xlab = "Date", ylab = "Random")
yields:
with lots of warnings about format not being a graphical parameter.

Resources