Site icon R-bloggers

It’s Time!

[This article was first published on R-SquareD, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
…to ggplot some xts objects. –

The xts package is fantastic for time-series data manipulation. You can easily convert to and apply functions to different frequencies, merge with other time series vertically and horizontally, and lag data. These are very helpful features that are cumbersome when working with a data.frame. Unfortunately, if you want to leverage ggplot to produce great looking plots, you cannot use xts objects natively.

It is fairly easy to convert from xts to to a data frame but the key is to get the date into its own column.

library(xts)
library(ggplot2)
library(ggthemes)
library(reshape2)
 
## Read in a csv file of prices 
ibm_url = "http://real-chart.finance.yahoo.com/table.csv?s=IBM&g=d&a=0&b=1&c=2005&ignore=.csv"
ibm_price_hist = read.csv(ibm_url, header = T, quote = "")

## Convert the data into an xts object for ease of date manipulation.
x.ibm_price_hist = as.xts(ibm_price_hist[,-1], order.by = as.Date(ibm_price_hist[,1]))
     
x.ibm_price_hist_monthly = to.monthly(x.ibm_price_hist$Close, OHLC=F)

I don’t like those four steps to get the price data into an xts object, so just create a personal library function to handle it. You can use the quantmod package which includes a function (getSymbols) to download prices and other data from various sources directly into xts objects. You can also just roll your own.

GetPrices = function(url) {
  price_hist = read.csv(url, header = T, quote = "")
  ## Convert the data into an xts object for ease of date manipulation.
  x.price_hist = as.xts(price_hist[,-1], order.by = as.Date(price_hist[,1]))
  
  return(x.price_hist)
}

x.ibm_price_hist = GetPrices(ibm_url)

x.ibm_price_hist_monthly = to.monthly(x.ibm_price_hist$Close, indexAt = "endof", OHLC=F)
tail(x.ibm_price_hist_monthly)
##             Close
## 2016-04-29 145.94
## 2016-05-31 153.74
## 2016-06-30 151.78
## 2016-07-29 160.62
## 2016-08-31 158.88
## 2016-09-27 156.77

To use ggplot with this data, we need to convert it back to a data.frame. This is a fairly simple process, but again, we don’t want to continually do it so create a function.

xts2data.frame = function(x) {
  df = data.frame(x=index(x), coredata(x))
  # Preserve the column names from the xts object 
  #  and use "Date" as the new column for new date column
  colnames(df) = c("Date", colnames(x))
  return(df)
}
 
df.ibm_price_history_monthly = xts2data.frame(x.ibm_price_hist_monthly)
tail(df.ibm_price_history_monthly)
##           Date  Close
## 136 2016-04-29 145.94
## 137 2016-05-31 153.74
## 138 2016-06-30 151.78
## 139 2016-07-29 160.62
## 140 2016-08-31 158.88
## 141 2016-09-27 156.77
ggplot(df.ibm_price_history_monthly) +
  geom_line(aes(x=Date, y=Close), size=1.5) +
  ggtitle("IBM Stock Price") + 
  ylab("Price Close (log 10 scale)") +
  scale_y_log10(breaks=pretty(df.ibm_price_history_monthly$Close)) +
  theme_economist_white()

If you want to use the group or facet features of ggplot for each time series in your object, you will need to “stack” the data. There are many ways to do this, but melt from the reshape2 package does a good job.

df.ibm_price_history = xts2data.frame(x.ibm_price_hist["2016-05-01::"])
df.ibm_price_history_stack = melt(df.ibm_price_history[,1:5], id=c("Date"), variable.name="Type", value.name="Price")

ggplot(df.ibm_price_history_stack) +
  geom_line(aes(x=Date, y=Price, group=Type, color=Type), size=1) +
  ggtitle("IBM") + 
  ylab("Price (log 10 scale)") +
  scale_y_log10(breaks=pretty(df.ibm_price_history_stack$Price)) +
  theme_economist_white()

ggplot(df.ibm_price_history_stack) +
  geom_line(aes(x=Date, y=Price), size=1) +
  ggtitle("IBM") + 
  ylab("Price (log 10 scale)") +
  scale_y_log10(breaks=pretty(df.ibm_price_history_stack$Price)) +
  facet_grid(Type ~ .) +
  theme_economist_white()

Those are not very helpful charts, but you should get the idea.

Here is a nice candlestick chart that looks much better and uses the data. It takes a little more data manipulation, but it is worth it.

x.ibm_ohlc_hist_monthly = to.monthly(x.ibm_price_hist$Close, indexAt = "endof", OHLC=T, name = c("Data"))
tail(x.ibm_ohlc_hist_monthly)
##            Data.Open Data.High Data.Low Data.Close
## 2016-04-29    152.52    152.53   144.00     145.94
## 2016-05-31    145.27    153.74   144.13     153.74
## 2016-06-30    152.51    155.35   143.50     151.78
## 2016-07-29    152.35    162.65   151.68     160.62
## 2016-08-31    161.45    163.53   158.32     158.88
## 2016-09-27    159.54    161.64   153.84     156.77
df.ibm_ohlc_hist_monthly = xts2data.frame(x.ibm_ohlc_hist_monthly)

# Need the direction
df.ibm_ohlc_hist_monthly$Direction = ifelse(df.ibm_ohlc_hist_monthly$Data.Close >= df.ibm_ohlc_hist_monthly$Data.Open, "UP", "DOWN")

ggplot(df.ibm_ohlc_hist_monthly) +
  geom_linerange(aes(x=Date, ymin=Data.Low, ymax=Data.High), size=.5) +
  geom_rect(aes(xmin = Date - 10, xmax = Date + 10, ymin = Data.Open, ymax = Data.Close, fill=Direction)) + 
  ggtitle("IBM Price Chart") + 
  ylab("Price (log 10 scale)") +
  scale_y_log10(breaks=pretty(df.ibm_ohlc_hist_monthly$Data.Close)) +
  theme_economist() +
  theme(legend.position = "none")

To leave a comment for the author, please follow the link and comment on their blog: R-SquareD.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.