plotting points within a date range specified with shiny slider bar - r

From a larger dataset, I want to only plot points that are within a min and max date that is specified with a shiny slider bar containing a date range. This post builds from a related post linked here. Data are contained at the bottom using dput.
The code/app below sequentially plots points as the date is increased with the slider bar. When I move the 2nd slider bar I want points no longer in the date range to be removed, which currenlty does not happen.
How do I subset the data so that only points (and paths) >= the min date and <= the max date are shown? It is not clear to me how to reference the two dates on the slider bar.
Thanks in advance.
library(ggplot2)
library(shiny)
ui <- fluidPage(
titlePanel("GPS Data Summary"),
sliderInput(inputId = "Order",
label = "Sequance of Observations",
min = as.Date(min(dat$PosiGMT)), max = as.Date(max(dat$PosiGMT)),
value = c(as.Date(min(dat$PosiGMT)), as.Date(min(dat$PosiGMT)))),
plotOutput("PointPlot")
)
server <- function(input, output) {
output$PointPlot <- renderPlot({
p <- ggplot(dat[as.Date(dat$PosiGMT) <= input$Order ,], (aes(x = GPSUTMEasting , y = GPSUTMNorthing ))) +
geom_point() + geom_path() +
xlim( min(dat$GPSUTMEasting), max(dat$GPSUTMEasting))+
ylim( min(dat$GPSUTMNorthing), max(dat$GPSUTMNorthing))
print(p)
})
}
shinyApp(ui = ui, server = server)
Data below
dat <- structure(list(GPSUTMNorthing =
c(4947787L, 4947945L, 4947957L,
4947954L, 4947797L, 4947835L, 4947825L, 4947784L, 4947842L, 4947839L,
4947789L, 4947807L, 4947839L, 4947845L, 4947779L, 4947824L, 4947824L,
4947772L, 4947824L, 4947821L, 4947816L, 4947809L, 4947840L, 4947829L,
4947820L),
GPSUTMEasting = c(600201L, 600910L, 600911L, 600907L,
601052L, 601038L, 601031L, 601066L, 600998L, 600995L, 601058L,
601038L, 600987L, 601071L, 601016L, 601002L, 601003L, 601003L,
600917L, 600916L, 600918L, 600923L, 600985L, 600980L, 600914L),
PosiGMT = structure(c(1360393200, 1360414800, 1360479600,
1360501200, 1360544400, 1360566000, 1360587600, 1360630800, 1360652400,
1360674000, 1360695600, 1360717200, 1360738800, 1360803600, 1360825200,
1360846800, 1360868400, 1360890000, 1360911600, 1360933200, 1360954800,
1360976400, 1360998000, 1361019600, 1361041200),
class = c("POSIXct", "POSIXt"), tzone = "") ),
.Names = c("GPSUTMNorthing", "GPSUTMEasting", "PosiGMT"),
row.names = c(1L, 2L, 5L, 6L, 8L, 9L, 10L, 12L, 13L, 14L, 15L,
16L, 17L, 20L, 21L, 22L, 23L, 24L, 25L, 26L, 27L, 28L, 29L, 30L, 31L),
class = "data.frame")

Hi input$Order is a vector of length 2, so input$Order[1] is the min and input$Order[2] the max, you can do something like this :
library(ggplot2)
library(shiny)
ui <- fluidPage(
titlePanel("GPS Data Summary"),
sliderInput(inputId = "Order",
label = "Sequance of Observations",
min = as.Date(min(dat$PosiGMT)), max = as.Date(max(dat$PosiGMT)),
value = c(as.Date(min(dat$PosiGMT)), as.Date(min(dat$PosiGMT)))),
plotOutput("PointPlot")
)
server <- function(input, output) {
output$PointPlot <- renderPlot({
### Filter by date
dat <- dat[as.Date(dat$PosiGMT) >= input$Order[1] & as.Date(dat$PosiGMT) <= input$Order[2] ,]
###
p <- ggplot(dat, (aes(x = GPSUTMEasting , y = GPSUTMNorthing ))) +
geom_point() + geom_path() +
xlim( min(dat$GPSUTMEasting), max(dat$GPSUTMEasting))+
ylim( min(dat$GPSUTMNorthing), max(dat$GPSUTMNorthing))
print(p)
})
}
shinyApp(ui = ui, server = server)

Related

Bold/highlight single line in multiple line chart when hover over using ggplotly

I just started learning R and I am creating an interactive line chart using ggplot2 and plotly.
Is there a way to bold/highlight the corresponding line in a multiple line graph when the mouse hovers over?
The line chart that I have is plotted according to the inputs and multiple lines will be plotted in a single line chart if there are multiple inputs.
This is the code I have in R Shiny.
data_sales <- structure(list(town = c("ANG MO KIO", "ANG MO KIO", "ANG MO KIO",
"BEDOK", "BEDOK", "BEDOK"), Date = structure(c(17167, 17198,
17226, 17167, 17198, 17226), class = "Date"), median_sales = c(336500,
355000, 375000, 359000, 361500, 360000), percentage_change_sales = c(NA,
5.49777117384844, 5.6338028169014, NA, 0.696378830083555, -0.414937759336098
), transaction_vol = c(56L, 41L, 89L, 70L, 70L, 101L), percentage_change_vol = c(NA,
-26.7857142857143, 117.073170731707, NA, 0, 44.2857142857143)), row.names = c(1L,
2L, 3L, 32L, 33L, 34L), class = "data.frame")
ui <- fluidPage(
titlePanel("Change in Sales by Town"),
verticalLayout(
pickerInput(inputId = "town",
label = "Town",
choices = c("Ang Mo Kio" = "ANG MO KIO",
"Bedok" = "BEDOK"),
options = list('actions-box' = TRUE),multiple = T,
selected = "ANG MO KIO"),
mainPanel("Trend in sales",
fluidRow( plotlyOutput("sales_percentage_plot")
)
)
)
)
server <- function(input, output){
#For Resale Price
output$sales_percentage_plot <-renderPlotly({
data<-data_sales[data_sales$town %in% input$town, ]
p<-ggplot(data, (aes(Date,percentage_change_sales,colour = town))) +
geom_line() +
geom_point()
p<-ggplotly(p)
p
})
}
shinyApp (ui=ui, server=server)
Thanks in advance for the help given!
A little bit dirty but simple solution is:
library(shiny)
library(shinyWidgets)
library(plotly)
data_sales <-
structure(
list(
town = c("ANG MO KIO", "ANG MO KIO", "ANG MO KIO",
"BEDOK", "BEDOK", "BEDOK"),
Date = structure(c(17167, 17198,
17226, 17167, 17198, 17226), class = "Date"),
median_sales = c(336500,
355000, 375000, 359000, 361500, 360000),
percentage_change_sales = c(
NA,
5.49777117384844,
5.6338028169014,
NA,
0.696378830083555,
-0.414937759336098
),
transaction_vol = c(56L, 41L, 89L, 70L, 70L, 101L),
percentage_change_vol = c(
NA,
-26.7857142857143,
117.073170731707,
NA,
0,
44.2857142857143
)
),
row.names = c(1L,
2L, 3L, 32L, 33L, 34L),
class = "data.frame"
)
normal_size <- 0.5
bold_size <- 1.0
ui <- fluidPage(titlePanel("Change in Sales by Town"),
verticalLayout(
pickerInput(
inputId = "town",
label = "Town",
choices = c("Ang Mo Kio" = "ANG MO KIO",
"Bedok" = "BEDOK"),
options = list('actions-box' = TRUE),
multiple = T,
selected = "ANG MO KIO"
),
mainPanel("Trend in sales",
fluidRow(plotlyOutput(
"sales_percentage_plot"
)))
))
server <- function(input, output) {
#For Resale Price
output$sales_percentage_plot <- renderPlotly({
data <- data_sales[data_sales$town %in% input$town,]
# default size vector
sizes <- rep(normal_size, length(unique(data$town)))
# capture plotly event
eventdata <- event_data("plotly_hover")
p <-
ggplot(data, (
aes(
Date,
percentage_change_sales,
colour = town,
size = town
)
)) +
geom_line() +
geom_point()
if (!is.null(eventdata)) {
# search selected row in data
x <- data %>%
filter(Date == eventdata$x &
percentage_change_sales == eventdata$y)
# change size vector
sizes[which(unique(data$town) == x$town)] <- bold_size
}
# change line and point size manually
p <- p +
scale_size_manual(values = sizes)
# without tooltip settings, "town" appears twice...
p <- ggplotly(p, tooltip = c("x", "y", "colour"))
p
})
}
shinyApp (ui = ui, server = server)
I don't know why sometimes hover event occurs twice in a row.

Reorder reactive ggplot

I'm trying to reorder the x axis by the values in the y axis. The x axis is a name, the y axis is an integer. Both are reactive, user defined inputs. I have created a datatable that renders in the correct order, but ggplot does not take that order. Instead it does an alphabetical order.
My current code is:
Packages
library(shiny)
library(readxl) # to load the data into R
library(tidyverse)
library(stringr)
library(DT)
library(tools)
library(magrittr)
Data
lpop <-read.csv("londonpopchange.csv", header=TRUE)
UI
# Define UI for application that plots features of movies
ui <- fluidPage(
# Sidebar layout with a input and output definitions
sidebarLayout(
# Inputs
sidebarPanel(
# Select variable for y-axis
selectInput(inputId = "y",
label = "Y-axis:",
choices = c("Mid Year 2016" = "MYE2016",
"Births" = "Births",
"Deaths" = "Deaths",
"Births minus Deaths" = "BirthsminusDeaths",
"Internal Migration Inflow" = "InternalMigrationInflow",
"Internal Migration Outflow" = "InternalMigrationOutflow",
"Internal Migration Net" = "InternalMigrationNet",
"International Migration Inflow" = "InternationalMigrationInflow",
"International Migration Outflow" = "InternationalMigrationOutflow",
"International Migration Net" = "InternationalMigrationNet"),
selected = "MYE2016"),
# Select variable for x-axis
selectInput(inputId = "x",
label = "X-axis:",
choices = c("Borough" = "Name"),
selected = "Name")
),
# Output
mainPanel(
h1(textOutput("MainTitle")),
br(),
plotOutput(outputId = "geom_bar"),
DT::dataTableOutput("mytable")
)
)
)
Server
# Define server function required to create the scatterplot
server <- function(input, output) {
#this creates the title
output$MainTitle <- renderText({
paste(input$y, "for London Boroughs")
})
#creates a data table that reacts to the user variable input and arranges
#by the y variable
df <- reactive({
lpop %>%
select(input$x, input$y, "WF") %>%
arrange_(.dots = input$y) #%>%
# setNames(1:2, c("x", "y"))
})
#outputs the user defined data frame
output$mytable = ({DT::renderDataTable({df()})})
# Create the bar plot object the plotOutput function is expecting
output$geom_bar <- renderPlot({
ggplot(data = df(), aes_string(x = input$x, y = input$y, fill = "WF")) +
geom_bar(stat = "identity") +
scale_fill_manual(values=c("#000000", "#00D253")) +
theme(axis.text.x = element_text(angle = 90)) +
xlab(input$x)
})
}
# Create a Shiny app object
shinyApp(ui = ui, server = server)
It renders as so: https://jwest.shinyapps.io/ShinyPopulation/
If I use the reorder function in ggplot, it amalgamates all "Names" into one bar, see below.
# Create the bar plot object the plotOutput function is expecting
output$geom_bar <- renderPlot({
ggplot(data = df(), aes_string(x = reorder(input$x, input$y), y = input$y, fill = "WF")) +
geom_bar(stat = "identity") +
scale_fill_manual(values=c("#000000", "#00D253")) +
theme(axis.text.x = element_text(angle = 90)) +
xlab(input$x)
})
}
How can I render it by the Y axis? Is it something to do with scale_x_discrete(limits = ...). If it is I am confused as to how i'm meant to reference the first column of the reactive df
The csv can be downloaded here: https://drive.google.com/file/d/1QLT8CX9XFSx3WU_tADyWgyddHYd3-VSp/view?usp=sharing
DPUT
structure(list(Code = structure(c(7L, 1L, 12L, 13L, 14L), .Label = c("E09000001",
"E09000002", "E09000003", "E09000004", "E09000005", "E09000006",
"E09000007", "E09000008", "E09000009", "E09000010", "E09000011",
"E09000012", "E09000013", "E09000014", "E09000015", "E09000016",
"E09000017", "E09000018", "E09000019", "E09000020", "E09000021",
"E09000022", "E09000023", "E09000024", "E09000025", "E09000026",
"E09000027", "E09000028", "E09000029", "E09000030", "E09000031",
"E09000032", "E09000033"), class = "factor"), Name = structure(c(6L,
7L, 12L, 13L, 14L), .Label = c("Barking and Dagenham", "Barnet",
"Bexley", "Brent", "Bromley", "Camden", "City of London", "Croydon",
"Ealing", "Enfield", "Greenwich", "Hackney", "Hammersmith and Fulham",
"Haringey", "Harrow", "Havering", "Hillingdon", "Hounslow", "Islington",
"Kensington and Chelsea", "Kingston upon Thames", "Lambeth",
"Lewisham", "Merton", "Newham", "Redbridge", "Richmond upon Thames",
"Southwark", "Sutton", "Tower Hamlets", "Waltham Forest", "Wandsworth",
"Westminster"), class = "factor"), Geography = structure(c(1L,
1L, 1L, 1L, 1L), .Label = "London Borough", class = "factor"),
MYE2016 = c(249162L, 7246L, 273239L, 181783L, 272078L), Births = c(2671L,
68L, 4405L, 2446L, 3913L), Deaths = c(1180L, 38L, 1168L,
895L, 1140L), BirthsminusDeaths = c(1491L, 30L, 3237L, 1551L,
2773L), InternalMigrationInflow = c(22189L, 856L, 21271L,
19109L, 22469L), InternalMigrationOutflow = c(25132L, 792L,
23324L, 20488L, 29113L), InternalMigrationNet = c(-2943L,
64L, -2053L, -1379L, -6644L), InternationalMigrationInflow = c(11815L,
756L, 5054L, 5333L, 7480L), InternationalMigrationOutflow = c(6140L,
441L, 3534L, 4336L, 4460L), InternationalMigrationNet = c(5675L,
315L, 1520L, 997L, 3020L), Other = c(-24L, -1L, -14L, 46L,
-3L), Estimated.Population..mid.2017 = c(253361L, 7654L,
275929L, 182998L, 271224L), WF = structure(c(1L, 1L, 1L,
1L, 1L), .Label = c("London Borough", "Waltham Forest"), class = "factor")), .Names = c("Code",
"Name", "Geography", "MYE2016", "Births", "Deaths", "BirthsminusDeaths",
"InternalMigrationInflow", "InternalMigrationOutflow", "InternalMigrationNet",
"InternationalMigrationInflow", "InternationalMigrationOutflow",
"InternationalMigrationNet", "Other", "Estimated.Population..mid.2017",
"WF"), row.names = c(NA, 5L), class = "data.frame")

Shiny app multiple regression

library(shiny)
ui <- fluidPage(
titlePanel("Linear model DARP"),
sidebarLayout(
sidebarPanel(
sliderInput(inputId = "area",
"select the service region area:",
min= 170,
max= 8000,
value=1001),
sliderInput(inputId = "crit..peak",
label="Choose Peak demand:",
min=10,
max=150,
value=39)
),
mainPanel(
tableOutput("table")
)
)
)
server <- function(input, output) {
output$table <- renderTable({
df_ln<-read.csv("F:/Project/Programme/ML/DAR Machine Learning TR Part A/train_darp_ln.csv")
Linearmodel_DARP<-lm(veh~area+crit..peak,data = df_ln)
new_demand1<-data.frame(area=input$area)
new_demand2<-data.frame(crit..peak=input$crit..peak
fleetsize<-predict(Linearmodel_DARP,newdata=c(new_demand1,new_demand2))
round(exp(fleetsize),0)
})
}
shinyApp(ui = ui, server = server)
I am getting error object crit..peak is not found when running the app
The app should take two inputs from the user through the slider and based on the multiple regression it will give a prediction of the predict command
please help as I need to do it soon for a project
structure(list(area = c(2217.7, 6537.4, 1705.5, 5634, 1260.5,
4797.7), density = c(0.13753, 0.016826, 0.18469, 0.021477, 0.25862,
0.027305), crit..CV = c(0.63954, 0.81437, 0.49909, 0.33935, 0.39148,
0.17489), crit..peak = c(49L, 26L, 41L, 20L, 39L, 18L), TW = c(21L,
47L, 54L, 48L, 17L, 41L), L = c(569L, 576L, 391L, 390L, 458L,
392L), s = c(7L, 3L, 3L, 6L, 3L, 2L), speed = c(18L, 26L, 20L,
30L, 24L, 33L), circuity = c(1.3284, 1.1494, 1.4597, 1.2725,
1.0486, 1.0792), cap = c(9L, 9L, 5L, 8L, 5L, 7L), mrt = c(1.5452,
2.3743, 1.5962, 2.6065, 2.1278, 2.6228), veh = c(4.605170186,
3.433987204, 4.718498871, 3.951243719, 4.060443011, 3.526360525
), veh.hrs = c(6.665569062, 5.523778231, 6.496186582, 5.71857256,
5.816843267, 5.256713817), veh.km = c(9.555940819, 8.781874769,
9.491918855, 9.119769942, 8.994897097, 8.753221378)), .Names = c("area",
"density", "crit..CV", "crit..peak", "TW", "L", "s", "speed",
"circuity", "cap", "mrt", "veh", "veh.hrs", "veh.km"), row.names = c(NA,
6L), class = "data.frame")
Ok, so your problem is probably due to the way you try to make your new data frame. You made two separate 1 dimensional data frames and then concatenated them, which generated a list of dataframes. To make a data frame with two or more variables, define them in your data frame definition or use cbind to join the data frames together:
new_demand <- data.frame(area = input$area,
crit..peak = input$crit..peak)
fleetsize <- predict(Linearmodel_DARP, newdata = new_demand)
This should solve your problem. In the future, when you get errors like error object ... is not found, the first thing to do is check that the objects you're generating are what you think they are. The class function would have told you that c(new_demand1, new_demand2) is a list not a data.frame
The error could be because of read.csv as it's missing header = T.
Let's try this chunk of code
server <- function(input, output) {
output$table <- renderTable({
df_ln <- read.csv("F:/Project/Programme/ML/DAR Machine Learning TR Part A/train_darp_ln.csv", header = T)
Linearmodel_DARP <- lm(veh~area+chrit..peak, data = df_ln)
new_demand1 <- data.frame(area=input$area)
new_demand2 <- data.frame(crit..peak=input$crit..peak)
fleetsize <- predict(Linearmodel_DARP, newdata=c(new_demand1, new_demand2))
round(exp(fleetsize), 0)
})
}

Flow map(Travel Path) Using Lat and Long in R

I am trying to plot flow map (for singapore) . I have Entry(Lat,Long) and Exit (Lat,long). I am trying to map the flow from entry to exit in singapore map.
structure(list(token_id = c(1.12374e+19, 1.12374e+19, 1.81313e+19,
1.85075e+19, 1.30752e+19, 1.30752e+19, 1.32828e+19, 1.70088e+19,
1.70088e+19, 1.70088e+19, 1.05536e+19, 1.44818e+19, 1.44736e+19,
1.44736e+19, 1.44736e+19, 1.44736e+19, 1.89909e+19, 1.15795e+19,
1.15795e+19, 1.15795e+19, 1.70234e+19, 1.70234e+19, 1.44062e+19,
1.21512e+19, 1.21512e+19, 1.95909e+19, 1.95909e+19, 1.50179e+19,
1.50179e+19, 1.24174e+19, 1.36445e+19, 1.98549e+19, 1.92068e+19,
1.18468e+19, 1.18468e+19, 1.92409e+19, 1.92409e+19, 1.21387e+19,
1.9162e+19, 1.9162e+19, 1.40385e+19, 1.40385e+19, 1.32996e+19,
1.32996e+19, 1.69103e+19, 1.69103e+19, 1.57387e+19, 1.40552e+19,
1.40552e+19, 1.00302e+19), Entry_Station_Lat = c(1.31509, 1.33261,
1.28425, 1.31812, 1.33858, 1.29287, 1.39692, 1.37773, 1.33858,
1.33322, 1.28179, 1.30036, 1.43697, 1.39752, 1.27637, 1.39752,
1.41747, 1.35733, 1.28405, 1.37773, 1.35898, 1.42948, 1.32774,
1.42948, 1.349, 1.36017, 1.34971, 1.38451, 1.31509, 1.31509,
1.37002, 1.34971, 1.31231, 1.39169, 1.31812, 1.44909, 1.29341,
1.41747, 1.33759, 1.44062, 1.31509, 1.38451, 1.29461, 1.32388,
1.41747, 1.27614, 1.39752, 1.39449, 1.33261, 1.31231), Entry_Station_Long = c(103.76525,
103.84718, 103.84329, 103.89308, 103.70611, 103.8526, 103.90902,
103.76339, 103.70611, 103.74217, 103.859, 103.85563, 103.7865,
103.74745, 103.84596, 103.74745, 103.83298, 103.9884, 103.85152,
103.76339, 103.75191, 103.83505, 103.67828, 103.83505, 103.74956,
103.88504, 103.87326, 103.74437, 103.76525, 103.76525, 103.84955,
103.87326, 103.83793, 103.89548, 103.89308, 103.82004, 103.78479,
103.83298, 103.69742, 103.80098, 103.76525, 103.74437, 103.80605,
103.93002, 103.83298, 103.79156, 103.74745, 103.90051, 103.84718,
103.83793), Exit_Station_Lat = structure(c(48L, 34L, 118L, 60L,
14L, 54L, 10L, 49L, 49L, 74L, 71L, 65L, 102L, 5L, 102L, 119L,
116L, 10L, 13L, 88L, 117L, 66L, 40L, 62L, 117L, 37L, 67L, 34L,
85L, 44L, 102L, 44L, 115L, 29L, 92L, 17L, 121L, 70L, 120L, 52L,
85L, 34L, 42L, 11L, 4L, 115L, 62L, 48L, 92L, 14L), .Label = c("1.27082",
"1.27091", "1.27236", "1.27614", "1.27637", "1.27646", "1.27935",
"1.28221", "1.28247", "1.28405", "1.28621", "1.28819", "1.28932",
"1.29287", "1.29309", "1.29338", "1.29341", "1.29461", "1.29694",
"1.29959", "1.29974", "1.30034", "1.30252", "1.30287", "1.30392",
"1.30394", "1.30619", "1.30736", "1.30842", "1.31139", "1.3115",
"1.31167", "1.31188", "1.31509", "1.31654", "1.31756", "1.31913",
"1.31977", "1.32008", "1.3205", "1.32104", "1.32388", "1.32573",
"1.32725", "1.32774", "1.33119", "1.33155", "1.33261", "1.33322",
"1.33474", "1.33554", "1.33759", "1.33764", "1.33858", "1.33921",
"1.34037", "1.34225", "1.34293", "1.3432", "1.34426", "1.34857",
"1.349", "1.34905", "1.35158", "1.35733", "1.35898", "1.36017",
"1.3625", "1.36849", "1.37002", "1.37121", "1.37304", "1.37666",
"1.37775", "1.3786", "1.37862", "1.38001", "1.38029", "1.3803",
"1.38178", "1.38269", "1.38295", "1.38399", "1.38423", "1.38451",
"1.38671", "1.38672", "1.38777", "1.38814", "1.3894", "1.39147",
"1.39169", "1.39189", "1.39208", "1.39389", "1.39449", "1.39452",
"1.39628", "1.39692", "1.39717", "1.39732", "1.39752", "1.39821",
"1.39928", "1.39962", "1.4023", "1.40455", "1.40511", "1.40524",
"1.40843", "1.40961", "1.41184", "1.41588", "1.41685", "1.41747",
"1.42526", "1.42948", "1.43256", "1.43697", "1.44062", "1.44909"
), class = "factor"), Exit_Station_Long = structure(c(59L, 19L,
27L, 4L, 65L, 3L, 63L, 6L, 6L, 21L, 93L, 121L, 9L, 56L, 9L, 32L,
16L, 63L, 44L, 23L, 50L, 12L, 54L, 11L, 50L, 71L, 87L, 19L, 7L,
118L, 9L, 118L, 49L, 90L, 96L, 31L, 45L, 61L, 38L, 2L, 7L, 19L,
117L, 47L, 34L, 49L, 11L, 59L, 96L, 65L), .Label = c("103.67828",
"103.69742", "103.70611", "103.72092", "103.73274", "103.74217",
"103.74437", "103.74529", "103.74745", "103.74905", "103.74956",
"103.75191", "103.7537", "103.75803", "103.76011", "103.76215",
"103.76237", "103.76449", "103.76525", "103.76648", "103.76667",
"103.76893", "103.7696", "103.77082", "103.77145", "103.77266",
"103.774", "103.77866", "103.78185", "103.78425", "103.78479",
"103.7865", "103.78744", "103.79156", "103.79631", "103.79654",
"103.79836", "103.80098", "103.803", "103.80605", "103.80745",
"103.80781", "103.80978", "103.81703", "103.82004", "103.82592",
"103.82695", "103.83216", "103.83298", "103.83505", "103.83918",
"103.83953", "103.83974", "103.84387", "103.84496", "103.84596",
"103.84673", "103.84674", "103.84718", "103.84823", "103.84955",
"103.85092", "103.85152", "103.85226", "103.8526", "103.85267",
"103.85436", "103.85446", "103.85452", "103.86088", "103.86149",
"103.86275", "103.86291", "103.86395", "103.86405", "103.86896",
"103.87087", "103.87135", "103.87534", "103.87563", "103.8763",
"103.87971", "103.88003", "103.88126", "103.88243", "103.88296",
"103.88504", "103.8858", "103.88816", "103.8886", "103.88934",
"103.89054", "103.89237", "103.89313", "103.8938", "103.89548",
"103.89719", "103.89723", "103.89854", "103.9003", "103.90051",
"103.90208", "103.90214", "103.9031", "103.90484", "103.90537",
"103.90597", "103.90599", "103.90663", "103.9086", "103.90902",
"103.9126", "103.9127", "103.91296", "103.91616", "103.9165",
"103.93002", "103.94638", "103.94929", "103.95337", "103.9884"
), class = "factor")), .Names = c("token_id", "Entry_Station_Lat",
"Entry_Station_Long", "Exit_Station_Lat", "Exit_Station_Long"
), row.names = c(10807L, 10808L, 10810L, 10815L, 10817L, 10818L,
10819L, 10820L, 10823L, 10824L, 10826L, 10827L, 10829L, 10831L,
10832L, 10833L, 10834L, 10835L, 10836L, 10838L, 10840L, 10841L,
10843L, 10847L, 10850L, 10852L, 10854L, 10855L, 10859L, 10861L,
10869L, 10872L, 10883L, 10886L, 10891L, 10895L, 10896L, 10897L,
10900L, 10902L, 10903L, 10906L, 10910L, 10911L, 10912L, 10913L,
10915L, 10920L, 10921L, 10924L), class = "data.frame")
I am trying to get something this : Map Flow
Just realized that the original solution usin geom_path was more complicated than necessary. geom_segmentworks without changing the data:
require(ggplot2)
require(ggmap)
basemap <- get_map("Singapore",
source = "stamen",
maptype = "toner",
zoom = 11)
g = ggplot(a)
map = ggmap(basemap, base_layer = g)
map = map + coord_cartesian() +
geom_curve(size = 1.3,
aes(x=as.numeric(Entry_Station_Long),
y=as.numeric(Entry_Station_Lat),
xend=as.numeric(as.character(Exit_Station_Long)),
yend=as.numeric(as.character(Exit_Station_Lat)),
color=as.factor(token_id)))
map
This solution leverages Draw curved lines in ggmap, geom_curve not working to implement curved lines on a map.
ggmaps used for simplicity - for more ambitious projects I would recommend leaflet.
Below the solution using a long data format with some prior data wrangling. It also uses straight lines instead of the curves above.
a %>%
mutate(path = row_number()) -> a
origin = select(a,token_id,Entry_Station_Lat,Entry_Station_Long,path)
origin$type = "origin"
dest = select(a,token_id,Exit_Station_Lat,Exit_Station_Long,path)
dest$type = "dest"
colnames(origin) = c("id","lat","long","path","type")
colnames(dest) = c("id","lat","long","path","type")
complete = rbind(origin,dest)
complete %>% arrange(path,type) -> complete
require(ggmap)
basemap <- get_map("Singapore",
source = "stamen",
maptype = "toner",
zoom = 11)
g = ggplot(complete, aes(x=as.numeric(long),
y=as.numeric(lat)))
map = ggmap(basemap, base_layer = g)
map + geom_path(aes(color = as.factor(id)),
size = 1.1)
If you want to plot it on an actual Google Map, and recreate the style of your linked map, you can use my googleway package that uses Google's Maps API. You need an API key to use their maps
library(googleway)
df$Exit_Station_Lat <- as.numeric(as.character(df$Exit_Station_Lat))
df$Exit_Station_Long <- as.numeric(as.character(df$Exit_Station_Long))
df$polyline <- apply(df, 1, function(x) {
lat <- c(x['Entry_Station_Lat'], x['Exit_Station_Lat'])
lon <- c(x['Entry_Station_Long'], x['Exit_Station_Long'])
encode_pl(lat = lat, lon = lon)
})
mapKey <- 'your_api_key'
style <- '[ { "stylers": [{ "visibility": "simplified"}]},{"stylers": [{"color": "#131314"}]},{"featureType": "water","stylers": [{"color": "#131313"},{"lightness": 7}]},{"elementType": "labels.text.fill","stylers": [{"visibility": "on"},{"lightness": 25}]}]'
google_map(key = mapKey, style = style) %>%
add_polylines(data = df,
polyline = "polyline",
mouse_over_group = "Entry_Station_Lat",
stroke_weight = 0.7,
stroke_opacity = 0.5,
stroke_colour = "#ccffff")
Note, to recreate the map using flight data, see the example given in ?add_polylines
You can also show other types of routes, for example, driving between the locations by using Google's Directions API to encode the driving routes.
df$drivingRoute <- lst_directions <- apply(df, 1, function(x){
orig <- as.numeric(c(x['Entry_Station_Lat'], x['Entry_Station_Long']))
dest <- as.numeric(c(x['Exit_Station_Lat'], x['Exit_Station_Long']))
dir <- google_directions(origin = orig, destination = dest, key = apiKey)
dir$routes$overview_polyline$points
})
google_map(key = mapKey, style = style) %>%
add_polylines(data = df,
polyline = "drivingRoute",
mouse_over_group = "Entry_Station_Lat",
stroke_weight = 0.7,
stroke_opacity = 0.5,
stroke_colour = "#ccffff")
Alternative answer using leaflet and geosphere
#get Packages
require(leaflet)
require(geosphere)
#format data
a$Entry_Station_Long = as.numeric(as.character(a$Entry_Station_Long))
a$Entry_Station_Lat = as.numeric(as.character(a$Entry_Station_Lat))
a$Exit_Station_Long = as.numeric(as.character(a$Exit_Station_Long))
a$Exit_Station_Lat = as.numeric(as.character(a$Exit_Station_Lat))
a$id = as.factor(as.numeric(as.factor(a$token_id)))
#create some colors
factpal <- colorFactor(heat.colors(30), pathList$id)
#create a list of interpolated paths
pathList = NULL
for(i in 1:nrow(a))
{
tmp = gcIntermediate(c(a$Entry_Station_Long[i],
a$Entry_Station_Lat[i]),
c(a$Exit_Station_Long[i],
a$Exit_Station_Lat[i]),n = 25,
addStartEnd=TRUE)
tmp = data.frame(tmp)
tmp$id = a[i,]$id
tmp$color = factpal(a[i,]$id)
pathList = c(pathList,list(tmp))
}
#create empty base leaflet object
leaflet() %>% addTiles() -> lf
#add each entry of pathlist to the leaflet object
for (path in pathList)
{
lf %>% addPolylines(data = path,
lng = ~lon,
lat = ~lat,
color = ~color) -> lf
}
#show output
lf
Note that as I mentioned before there is no way of geosphering the paths in such a small locality - the great circles are effectively straight lines. If you want the rounded edges for sake of aesthetics you may have to use the geom_curve way described in my other answer.
I've also written the mapdeck library to make visualisations like this more appealing*
library(mapdeck)
set_token("MAPBOX_TOKEN") ## set your mapbox token here
df$Exit_Station_Lat <- as.numeric(as.character(df$Exit_Station_Lat))
df$Exit_Station_Long <- as.numeric(as.character(df$Exit_Station_Long))
mapdeck(
style = mapdeck_style('dark')
, location = c(104, 1)
, zoom = 8
, pitch = 45
) %>%
add_arc(
data = df
, origin = c("Entry_Station_Long", "Entry_Station_Lat")
, destination = c("Exit_Station_Long", "Exit_Station_Lat")
, layer_id = 'arcs'
, stroke_from_opacity = 100
, stroke_to_opacity = 100
, stroke_width = 3
, stroke_from = "#ccffff"
, stroke_to = "#ccffff"
)
*subjectively speaking
I would like to leave an alternative approach for you. What you can do is to restructure your data. Right now you have two columns for entry stations and the other two for exit stations. You can create one column for long, and another for lat by combing these columns. The trick is to use rbind() and c().
Let's have a look of this simple example.
x <- c(1, 3, 5)
y <- c(2, 4, 6)
c(rbind(x, y))
#[1] 1 2 3 4 5 6
Imagine x is long for entry stations and y for exit stations. 1 is longitude for a starting point. 2 is longitude where the first journey ended. As far as I can see from your sample data, it seems that 3 is identical 2. You could remove duplicated data points for each token_id. If you have a large set of data, perhaps this is something you want to consider. Back to the main point, you can create a column with longitude in the sequence you want with the combination of the two functions. Since you said you have date information, make sure you order the data by date. Then, the sequence of each journey appears in the right way in tmp. You want to do this with latitude as well.
Now we look into your sample data. It seems that Exit_Station_Lat and Exit_Station_Long are in factor. The first operation is to convert them to numeric. Then, you apply the method above and create a data frame. I called your data mydf.
library(dplyr)
library(ggplot2)
library(ggalt)
library(ggthemes)
library(raster)
mydf %>%
mutate_at(vars(Exit_Station_Lat: Exit_Station_Long),
funs(as.numeric(as.character(.)))) -> mydf
group_by(mydf, token_id) %>%
do(data.frame(long = c(rbind(.$Entry_Station_Long,.$Exit_Station_Long)),
lat = c(rbind(.$Entry_Station_Lat, .$Exit_Station_Lat))
)
) -> tmp
Now let's get a map data from GADM. You can download data using the raster package.
getData(name = "GADM", country = "singapore", level = 0) %>%
fortify -> singapore
Finally, you draw a map. The key thing is to use group in aes in geom_path(). I hope this will let you move forward.
ggplot() +
geom_cartogram(data = singapore,
aes(x = long, y = lat, map_id = id),
map = singapore) +
geom_path(data = tmp,
aes(x = long, y = lat, group = token_id,
color = as.character(token_id)),
show.legend = FALSE) +
theme_map()

Error "arguments imply differing number of rows" when subsetting data with Shiny/ggplot2

I am afraid I am stuck.
I have a simple Shiny script with the intention of subsetting a dataframe based on user input and plot two variables in a scatterplot. When running the script I always get the error "Error in data.frame(x = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, : arguments imply differing number of rows: 1786, 2731". All I know is this error occurs when data is n_col!=n_row in a dataframe. However, I do not see how this can be the issue here. What buffles me is, if I execute the snippet below , the plot is drawn without problems:
#test4 <- subset(test2, grepl("PLANT1", test2$PLANTS))
#ggplot(test4, aes(x=test4$HOUR, y=test4$PRICE_NO)) +
geom_point(shape=1)
All I am doing is substituting the string with input$plant from ui.r.
Here is my Main window code:
###################################
# Launch App
###################################
#install.packages("shiny")
#install.packages("ggplot2")
library(shiny)
library(ggplot2)
#load data
#data <- read.csv2(file="C:/data.csv",head=FALSE)
#test4 <- subset(test2, grepl("PLANT1", test2$PLANTS))
#ggplot(test4, aes(x=test4$HOUR, y=test4$PRICE_NO)) +
geom_point(shape=1)
runApp("C:/PATH/")
My server.r
library(shiny)
library(ggplot2)
# Define Input to Plot
shinyServer(function(input, output) {
output$distPlot <- renderPlot({
# Draw Plot
test4 <- subset(test2, grepl(input$plant, test2$PLANTS))
ggplot(test4, aes(x=test4$HOUR, y=test4$PRICE_NO)) +
geom_point(shape=1)
})
})
My ui.r
library(shiny)
# Title
shinyUI(fluidPage(
titlePanel("TITLE"),
#Sidebar Layout
sidebarLayout(
sidebarPanel(
textInput("plant",
label = h3("Plant:"),
value = "PLANT1")
),
#
mainPanel(
plotOutput("distPlot")
)
)
))
Sample data as requested:
test2
plants HOUR PRICE
plant1 1 12,45
plant1 2 15,52
plant1 3 15,45
plant1 4 78,12
plant1 5 72,12
plant2 1 78,72
plant2 2 72,52
plant2 3 75,52
plant2 4 78,11
Conditional on what I mentioned in the comment regarding the use of subset, you can proceed as follows (you don't need to use grepl here)
test4 <- subset(test2, test2$plants==input$plant)
ggplot(test4, aes(x=HOUR, y=PRICE)) +
geom_point(shape=1)
ui. R
library(shiny)
# Title
shinyUI(fluidPage(
titlePanel("TITLE"),
#Sidebar Layout
sidebarLayout(
sidebarPanel(
selectInput("plant",
label = h3("Plant:"),
choices = c("plant1","plant2"),
selected="plant1")
),
#
mainPanel(
plotOutput("distPlot")
)
)
))
server.R
library(shiny)
library(ggplot2)
test2<-readRDS("data\\test2.rds")
# Define Input to Plot
shinyServer(function(input, output) {
output$distPlot <- renderPlot({
# Draw Plot
test4 <- subset(test2, test2$plants==input$plant)
ggplot(test4, aes(x=HOUR, y=PRICE)) +
geom_point(shape=1)
})
})
Your sample data which is in data folder inside the app:
test2<-structure(list(plants = structure(c(1L, 1L, 1L, 1L, 1L, 2L, 2L,
2L, 2L), .Label = c("plant1", "plant2"), class = "factor"), HOUR = c(1L,
2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L), PRICE = structure(c(1L, 3L,
2L, 8L, 4L, 9L, 5L, 6L, 7L), .Label = c("12,45", "15,45", "15,52",
"72,12", "72,52", "75,52", "78,11", "78,12", "78,72"), class = "factor")), .Names = c("plants",
"HOUR", "PRICE"), class = "data.frame", row.names = c(NA, -9L
))

Resources