Drawing a line on time series plot - r

I have the next time series object, which I plot it using plot:
ts <- ts(c(1:4,2:5,3:6,4:7,5:8,6:9,7:10), frequency = 4)
plot(ts)
Plot of the ts
Now, I would like to draw a line between the first and the last observation using abline, but, although R doesn't show any error, it seems that it doesn't work when using it on a plot of time series. The code used to try to draw the line was:
abline(a = 1, b = (ts[length(ts)]- ts[1]) / (length(ts)-1))
Did anyone had the same problem and manage to solve it?

ts <- ts(c(1:4,2:5,3:6,4:7,5:8,6:9,7:10), frequency = 4)
plot(ts, xlim=c(1,8), type="o")
x1 <- 1; y1 <- ts[1]
x2<- 7.75; y2 <- ts[length(ts)]
abline(a = y1-x1*(y1-y2)/(x1-x2), b = (y1-y2)/(x1-x2) )
grid()

I am not sure that I fully understand what you want to achieve. But the following may be of help.
You may use the following simple code using lines:
# your code
ts <- ts(c(1:4,2:5,3:6,4:7,5:8,6:9,7:10), frequency = 4)
plot(ts)
# drawing a blue line from (1, 1) to (8, 10)
lines(x = c(1, 8), y = c(1,10), col="blue")
which yields the following simple plot

Related

Converting a plotted line into a model object

Let's say I have a series of points between which I want to plot straight lines:
x <- c(0, 2, 4, 7, 12)
y <- c(0, 0, 4, 5, 0)
plot(x, y, type = 'l')
How would I go about turning this plotted line into a simple model object? For instance, something with which I would be able to use the stats::predict() function to do something like this:
model.object <- ???
predict(model.object, data.frame(x = 3))
Output:
2
Or, at the very least, is there some way R can identify the slopes and intercepts of each of these lines between the points so I could manually create a piecewise function using if-statements?
While it's a bit different than predict, you can use approxfun to do interpolation between points
f <- approxfun(x, y)
f(3)
# [1] 2
Note that it just takes a vector of x values rather than a data.frame to make predictions.

How do I plot multiple lines on the same graph?

I am using the R. I am trying to use the "lines' command in ggplot2 to show the predicted values vs. the actual values for a statistical model (arima, time series). Yet, when I ran the code, I can only see a line of one color.
I simulated some data in R and then tried to make plots that show actual vs predicted:
#set seed
set.seed(123)
#load libraries
library(xts)
library(stats)
#create data
date_decision_made = seq(as.Date("2014/1/1"), as.Date("2016/1/1"),by="day")
date_decision_made <- format(as.Date(date_decision_made), "%Y/%m/%d")
property_damages_in_dollars <- rnorm(731,100,10)
final_data <- data.frame(date_decision_made, property_damages_in_dollars)
#aggregate
y.mon<-aggregate(property_damages_in_dollars~format(as.Date(date_decision_made),
format="%W-%y"),data=final_data, FUN=sum)
y.mon$week = y.mon$`format(as.Date(date_decision_made), format = "%W-%y")`
ts = ts(y.mon$property_damages_in_dollars, start = c(2014,1), frequency = 12)
#statistical model
fit = arima(ts, order = c(4, 1, 1))
Here were my attempts at plotting the graphs:
#first attempt at plotting (no second line?)
plot(fit$residuals, col="red")
lines(fitted(fit),col="blue")
#second attempt at plotting (no second line?)
par(mfrow = c(2,1),
oma = c(0,0,0,0),
mar = c(2,4,1,1))
plot(ts, main="as-is") # plot original sim
lines(fitted(fit), col = "red") # plot fitted values
legend("topleft", legend = c("original","fitted"), col = c("black","red"),lty = 1)
#third attempt (plot actual, predicted and 5 future values - here, the actual and future values show up, but not the predicted)
pred = predict(fit, n.ahead = 5)
ts.plot(ts, pred$pred, lty = c(1,3), col=c(5,2))
However, none of these seem to be working correctly. Could someone please tell me what I am doing wrong? (note: the computer I am using for my work does not have an internet connection or a usb port - it only has R with some preloaded packages. I do not have access to the forecast package.)
Thanks
Sources:
In R plot arima fitted model with the original series
R fitted ARIMA off by one timestep? pkg:Forecast
Plotting predicted values in ARIMA time series in R
You seem to be confusing a couple of things:
fitted usually does not work on an object of class arima. Usually, you can load the forecast package first and then use fitted.
But since you do not have acces to the forecast package you cannot use fitted(fit): it always returns NULL. I had problems with fitted
before.
You want to compare the actual series (x) to the fitted series (y), yet in your first attempt you work with the residuals (e = x - y)
You say you are using ggplot2 but actually you are not
So here is a small example on how to plot the actual series and the fitted series without ggplot.
set.seed(1)
x <- cumsum(rnorm(10))
y <- stats::arima(x, order = c(1, 0, 0))
plot(x, col = "red", type = "l")
lines(x - y$residuals, col = "blue")
I Hope this answer helps you get back on tracks.

R: Plot lines are very thick

When using matplot to plot a matrix using:
matplot(t, X[,1:4], col=1:4, lty = 1, xlab="Time", ylab="Stock Value")
my graph comes out as:
How do I reduce the line thickness? I previously used a different method and my graph was fine:
I have tried manupilating lwd but to no avail.
Even tried plot(t, X[1:4097,1]), yet the line being printed is very thick. Something wrong with my R?
EDIT: Here is the code I used to produce the matrix X:
####Inputs mean return, volatility, time period and time step
mu=0.25; sigma=2; T=1; n=2^(12); X0=5;
#############Generating trajectories for stocks
##NOTE: Seed is fixed. Changing seed will produce
##different trajectories
dt=T/n
t=seq(0,T,by=dt)
set.seed(201)
X <- matrix(nrow = n+1, ncol = 4)
for(i in 1:4){
X[,i] <- c(X0,mu*dt+sigma*sqrt(dt)*rnorm(n,mean=0,sd=1))
X[,i] <- cumsum(X[,i])
}
colnames(X) <- paste0("Stock", seq_len(ncol(X)))
Just needed to add type = "l" to matplot(....). Plots fine now.
matplot(t, X[,1:4], col=1:4, type = "l", xlab="Time", ylab="Stock Value")

Distortions in multipanel plots

If I plot a data and use lines to superimpose the same data points on the graph, I get the same data points. Lets say
x<-rnorm(100)
plot(x, type="p")
lines(x, type="p",pch=2)
However, I have realized that there is a distortion in R plots when the same is done in a multipanel graph. It seems R is unable to recall the exact values on the y-axis when you plot the same data again. A simple code below shows the outputs from "plot" and "lines" are not the same.
set.seed(1000)
Range<-rbind(rep(0,4),c(100,100,1,100));thres<-70
Ylab<-c("MAD","Bias","CP","CIL")
X<-list(EVI=cbind(runif(10,0,100),runif(10,0,100),
runif(10,0,1),runif(10,0,100)),
Qp=cbind(runif(10,0,100),runif(10,0,100),runif(10,0,1),runif(10,0,100)))
Plot<-function(x,Pch=1,thres)
{
par(mfrow=c(1,4),las=2)
for(j in 1:4)
{
plot(x[,j],xaxt = "n",xlab="Estimator",
ylab=Ylab[j],type = "p", pch = Pch, ylim=Range[,j])
par(mfg=c(1,j))
axis(1, at=1:nrow(x), labels=LETTERS[1:nrow(x)])
if(j!=3){
par(mfg=c(1,j))
abline(h=thres,col=2)
}else{
par(mfg=c(1,j))
abline(h=c(0.90,0.95,0.99),lty=c(2,1,2),col=rep(2,3))
}
}
}
Line<-function(x,Pch)
{
for(j in 1:ncol(x)) {
par(mfg=c(1,j))
lines(x[,j], type = "p", pch = Pch,col=2)
}
}
lapply(X,function(dat)Plot(dat,thres=thres))
## First panel
Line(X$EVI,Pch=2)
## Move to second panel
Line(X$Qp,Pch=2)
What explains the distortions in the positioning of the points in the 3rd column? Note that, I have included the range of each data courtesy #WhiteViking in the "Plot" function. However, the distortion keeps showing. Thank you
The problem is in the ordering of 'plot' and 'lines'.
Code like this, with all 3 'plot' commands upfront:
set.seed(1)
X <- cbind(rnorm(20), 2 * rnorm(20), 3 * rnorm(20))
par(mfrow = c(1,3))
for (i in 1:3) {
plot(X[,i])
}
for (i in 1:3) {
par(mfg = c(1,i))
lines(X[,i], type = "p", col = 2, pch = 3)
}
yields misaligment:
In the example above the first 'lines' command that get executed bases its scaling on the last 'plot' that happened. Since that had a larger vertical range than the first, the scaling of the 'lines' is incorrect.
Whereas structured like so:
set.seed(1)
X <- cbind(rnorm(20), 2 * rnorm(20), 3 * rnorm(20))
par(mfrow = c(1,3))
for (i in 1:3) {
par(mfg = c(1,i))
plot(X[,i])
lines(X[,i], type = "p", col = 2, pch = 3)
}
it gives correct alignment of 'plot' and 'lines':
You'll probably have to rework your code to group 'plot' and 'lines' together for each sub-plot.
When the third column is converted to percentages, the ylim becomes uniform and hence there isn't such distortion. However, it will be good to get a way around it instead of such adhoc transformation
plot() sets up a coordinate system via plot.window based on the range of the data. This information is apparently stored in par(usr) for the latest plot, which means that if you want to revisit older plots, you should store those usr values and reset them accordingly,
set.seed(123)
d1 <- data.frame(x=1:10, y=rnorm(10))
d2 <- data.frame(x=1:10, y=10*rnorm(10))
par(mfrow=c(1,2),mar=c(2.5,2.5,0,0))
plot(d1, type="p")
usr1 <- par("usr")
plot(d2, type="p")
usr2 <- par("usr")
par(mfg=c(1,1), usr=usr1)
points(d1, col="red", pch=3)
par(mfg=c(1,2), usr=usr2)
points(d2, col="red", pch=3)

Drawing an interval on the graph using vertical line in R ?

install.packages("devtools")
library(devtools)
devtools::install_github("google/CausalImpact")
library(CausalImpact)
set.seed(1)
x1 <- 100 + arima.sim(model = list(ar = 0.999), n = 100)
y <- 1.2 * x1 + rnorm(100)
y[71:100] <- y[71:100] + 10
data <- cbind(y, x1)
pre.period <- c(1, 70)
post.period <- c(71, 100)
impact <- CausalImpact(data, pre.period, post.period)
plot(impact, "cumulative")
Say i want the graph to show an interval from 71-100 with the x scales starting at 1 from the first dotted line any ideas on how to do this?
Does anyone have any idea how to add a second vertical dotted line depicting an interval on the graph? Thanks.
You can use abline() to add lines to a graph, with the argument v = 70 setting a vertical line at x = 70. I'm not sure how to restart the x-scale from that point however - it doesn't seem like something that would be possible but perhaps someone else knows how.
You can reset the axes using this.
In your initial plot command, set xaxt = "n" This ensures that the plot function does not mark the axes.
You can then draw the abline(v=70) as mentioned above.
Then use axis(1,at=seq(60,80,by=1),las=1) 1 stands for x-axis and in the at attribute, mention the x limits you want. I've put in 60 to 80 as an example.

Resources