library(rmarkdown) #used for syntax highlighting in this document
library(shiny)
library(jsonlite)
library(dygraphs)
library(xts)
library(dplyr)
library(forecast)
library(data.table)
library(readr)read in file of item ids from website and parse
url = "http://eve-files.com/chribba/typeid.txt"
df = read_fwf(url, fwf_empty(url), skip = 2)
colnames = read_table(url, n_max = 1)
names(df) = names(colnames)
item.ids = na.omit(df)
item.ids$typeID<-as.numeric(item.ids$typeID)
item.ids<-item.ids[-c(1:17),] #remove first 17 because Galaxies, etc dont have prices but they do have item numberscreate a Shiny UI
The UI is a FluidPage which is stored as an R object (named ‘ui’). The UI is composed of:
- a title panel
- a sidebar (which allows the user to select:
- items to view in the graph
- attribute (low price, avg price, etc) they wish to view
- main panel (which displays the graph)
ui<-fluidPage(
#title panel
titlePanel("EVE Item Price Graph"),
#sidebar panel
sidebarLayout(
sidebarPanel(
helpText("EVE Item Price Graph"),
#item selector
selectizeInput('var.name', label = NULL, choices = item.ids$typeName, multiple=T,selected=item.ids$typeName[1],options = list(maxItems = 100,maxOptions=5)),
#dropdown for options
selectInput("var.col",
label = "Choose a variable to display",
choices = c("lowPrice","avgPrice","highPrice","volume","orders"),
selected = "lowPrice")
),
mainPanel(dygraphOutput("forecast"))
))Create a Shiny Server
The server takes in the var name from the text input, converts it to a number, retrieves the data from a website then returns the time series.
server <- shinyServer(function(input, output) {the getData() function takes in an item name, converts it to a number and retrieves the price data for that item via the eve-marketdata API
getData<-function(x){
item.id <-item.ids$typeID[which(item.ids$typeName == x)] #user chedked text name, this converts to number
eve.url <- paste0("http://eve-marketdata.com/api/item_history2.json?char_name=demo®ion_ids=10000002&type_ids=",item.id,"&days=100")
eve.data <- data.frame(fromJSON(txt = eve.url))$emd.row
eve.data$date <- as.Date(eve.data$date)
data <- as.vector(as.numeric(eve.data[, input$var.col]))
xxx <- xts(data, order.by = eve.data$date)
colnames(xxx) <- x
xxx
}the getColumns() function handles changes to the UI based on user input. The need() function throws an error message if the user did not select a value for something that is required.
getColumns <- reactive({
#cat(input$var.name) #useful for debugging. prints to console
shiny::validate(need(input$var.name!="", "Please select a data set"))
shiny::validate(shiny::need(input$var.col != "", "Please select a column to display"))
ans <- lapply(input$var.name, function(x) {
tryCatch(getData(x),error=function(x){NULL})
})
do.call(cbind, ans)
})the getForecast() function fits an ARIMA model which forecasts 10 days ahead. Note that the dates need to be incremented to match correctly on the dygraph.
getForecast<-function(data){
fit <- Arima(data, order=arimaorder(auto.arima(data)),include.drift = T)
pred = forecast(fit, h = 10)
plot(pred)
actual<- fit$x
predicted<-pred$mean
#upper <- pred$upper[,'95%']
#lower <- pred$lower[,'95%']
#trend <- as.numeric(pred$fitted)
ddnames<-colnames(data)[1]
data<-data.frame(c(as.vector(actual),rep(NA, length(predicted))),c(rep(NA, nrow(actual)),predicted))
colnames(data)<-c(ddnames,paste0(ddnames," predicted"))
final.date<-index(actual)[length(index(actual))]
dates<-c(as.Date(index(actual)),seq.Date(from=final.date,to=final.date+9,by = "day"))
data<-xts(data,order.by = dates)
data
}outputs dygraph with arima forecast. Forecast for each EVE item is generated in getForecast. The dyRangeSelector() is what allows the dygraph to zoom in on a certain area.
output$forecast<-renderDygraph({
data <- getColumns()
resForecasts<-lapply(data,function(data){
getForecast(data)
})
data<-do.call(cbind,resForecasts)
dygraph(data,main = "Eve Item Price Comparison Graph",xlab = "day",ylab = "item price") %>% dyRangeSelector()
})
})run the application by telling Shiny which variables the UI and server logic are stored in.
shinyApp(ui, server)