Reputation: 477
I'm unable to add a vertical, or horizontal line to my graph. I feel I'm missing something very simple, but I can't seem to find it. I've copied some examples from the internet but it won't work. What am I doing wrong?
This is what I'm trying:
library(quantmod)
getSymbols("^FTSE", src="yahoo", from=as.Date('2004-01-01'),
to=as.Date('2013-01-01'), periodicity="weekly")
plot(FTSE$FTSE.Close)
abline(v='2008-01-01', col="red")
I've also tried:
abline(h = 5000, col="red")
and
abline(h = mean(FTSE$FTSE.Close), col="red")
But they also won't work. No lines are shown.
I just want a vertical line. I'm using RStudio.
Upvotes: 2
Views: 6208
Reputation: 72683
This probably should be issued at CRAN. (This was already issued at github, solution is posted in the other answer.)
Here's a workaround.
Following this answer, we could plot a vertical constant rather with lines
than with abline
. plot.xts
, which is used when we plot a "xtx"
object, seems to be somewhat buggy or messy written as it also a comment signalizes in the linked answer, and which suggests to use zoo::plot.zoo
instead.
From another answer we learn, that we may use .index()
to extract the indices that are below the data, similar to factors where the values lie below the labels.
However, plot.zoo
prunes the dates according to an unknown smoothing algorithm (which probably can be figured out by looking deeply into zoo::plot.zoo
), and our date we're plotting could hit precisely such a "black hole". One possible solution is to give plot.zoo
a sapply
broadside of x-coordinates. I've written a function genXcords
genXcords <- function(data, date, tadj=0, ladj=0) {
idx <- as.Date(as.POSIXct(.index(data), origin="1970-01-01"))
se <- seq(as.Date(date) - 5 - tadj, by="day", length.out=21 + ladj)
y.crds <- .index(data)[which(min(se) < idx & idx < max(se))]
return(y.crds)
}
that first pulls out the dates from the numerical indices. Next, it creates a sequence of dates containing the date to be plotted somewhere within. Note the adjustment parameters tadj
and ladj
, because will will need some fine-tuning afterwards. (Probably the function itself has to be further refined!) Eventually, the function throws a battery of x-coordinates which we can try to plot.
Now let's test genXcords
method on an example.
# load package
library(xts)
# get data
data(sample_matrix)
sample.xts <- as.xts(sample_matrix)
# create line data
y.cords <- genXcords(sample.xts, "2007-05-16", -6, -18) # note the adjustment!
# plot
zoo::plot.zoo(sample.xts[,"Close"])
invisible(sapply(y.cords, function(x) lines(x=rep(x, 100),
y=seq(0, max(sample.xts$Close) + 10, length.out=100),
col="red", lty=2, lwd=2)))
I manually adjusted the tadj
and ladj
parameters until just one single vertical line appeared at the right place. This resulted in the plot below.
Note: Unfortunately I couldn't get it to work with the FTSE
data. But in principle, as one can see it works, and instead of deleting my code I put it here.
Upvotes: 2
Reputation: 72683
Alternatively, we will have to use xts::addEventLines
.
There was actually an issue opened at github on Feb, 2015 that abline
simply won't work with the new plot.xts
and we should use the alternative.
library(quantmod)
getSymbols("^FTSE", src="yahoo", from=as.Date('2004-01-01'),
to=as.Date('2013-01-01'), periodicity="weekly")
plot(FTSE$FTSE.Close)
# abline(v='2008-01-01', col="red") # won't work
# alternative
events <- xts("", as.Date("2008-01-01"))
addEventLines(events, col="red", lwd=2)
Note: It's also possible to define multiple event lines, e.g. events <- xts(letters[1:3], as.Date(c("2008-01-01", "2009-01-01", "2010-01-01")))
.
Upvotes: 2
Reputation: 2945
You want to use the v
argument (for vertical) not the h
argument (for horizontal). Here's a reproducible example:
d <- data.frame("y" = 1:5,
"dates" = paste0("2012-01-0", 1:5))
plot(d$y ~ d$dates)
abline(v = which(d$dates == "2012-01-01"), col = "red")
Upvotes: 0
Reputation: 8110
This is an interesting issue. Here is my workaround. I took the row index and made them into a column, then I translated the plot into ggplot
so that I could have a little more control on the plot. Let me know if anything in the code is ambiguous.
library(tidyverse)
library(quantmod)
getSymbols("^FTSE", src="yahoo", from=as.Date('2004-01-01'),
to=as.Date('2013-01-01'), periodicity="weekly")
FTSE %>%
as.data.frame() %>%
rownames_to_column("date") %>%
mutate(date = lubridate::ymd(date)) %>%
ggplot(aes(date,FTSE.Close ))+
geom_line()+
geom_vline(xintercept = as.Date('2008-01-01'), col="red")+
scale_y_continuous(breaks = scales::pretty_breaks(6),
sec.axis = sec_axis(trans = ~., breaks = scales::pretty_breaks(6)))+
scale_x_date(date_labels = "%b %d %Y", date_breaks = "2 years")+
ggtitle("FTSE.Close",subtitle = "2014-01-01/2012-12-27")+
theme(axis.title = element_blank(),
axis.line.x = element_line(colour = "black"),
axis.ticks.x = element_line(colour = "black"),
axis.line.y = element_blank(),
axis.ticks.y = element_blank(),
panel.background = element_blank(),
panel.grid.major = element_line(colour = "gray"))
Upvotes: 2