How to render multiple values in ggplot title in a Shiny app? - r

I'm having some problems with my ggplot title in this Shinyapp. I'm comparing countries and I want the countries the plot shows (colour = input$stat) to also be visible in the ggplot title. With the current code I'm only getting the first one. Is there perhaps an elegant solution to this problem?
If I'm comparing France, The United Kingdom and Spain, I want the title to be:
"Coronalandskampen, France, The United Kingdom, Spain"
library(tidyverse)
library(readxl)
library(httr)
library(zoo)
library(caTools)
library(shiny)
library(data.table)
#Get data
url <- paste("https://www.ecdc.europa.eu/sites/default/files/documents/COVID-19-geographic-disbtribution-worldwide-",format(Sys.time(), "%Y-%m-%d"), ".xlsx", sep = "")
GET(url, authenticate(":", ":", type="ntlm"), write_disk(tf <- tempfile(fileext = ".xlsx")))
df <- read_excel(tf)
df <- df %>%
rename(land = countriesAndTerritories,
`Antal fall` = cases,
`Antal döda` = deaths) %>%
arrange(land, dateRep) %>%
group_by(land) %>%
mutate(`Antal döda, kumulativt` = cumsum(`Antal döda`),
`Antal fall, kumulativt` = cumsum(`Antal fall`)) %>%
ungroup() %>%
filter(`Antal döda, kumulativt` > 10) %>%
group_by(land) %>%
mutate(antal_dagar = row_number(),
start_datum = min(dateRep),
`Antal Fall, rullande medeltal över sju dagar` = rollmean(`Antal fall`, 7, fill = NA),
`Antal döda, rullande medeltal över sju dagar` = rollmean(`Antal döda`, 7, fill = NA)) %>%
ungroup() %>%
mutate(`Döda per 100 000 invånare` = `Antal döda, kumulativt` * 100000 / popData2019) %>%
select(land, antal_dagar, `Antal fall`, `Antal fall, kumulativt`, `Antal döda`, `Antal döda, kumulativt`, `Döda per 100 000 invånare`,
`Antal Fall, rullande medeltal över sju dagar`, `Antal döda, rullande medeltal över sju dagar`, start_datum, geoId)
ui <- fluidPage(
navbarPage("Statistik Covid-19",
sidebarLayout(
sidebarPanel(
selectInput("stat", "Välj länder:", choices = unique(df$land), selected = "Sweden", multiple = TRUE),
varSelectInput("var", "Variabel:", df[c(3,4,5,6,7, 8, 9)])),
mainPanel(plotOutput("covid"))
)))
server <- function(input, output, session) {
df_graf <- reactive({df %>%
req(input$stat) %>%
filter(land %in% input$stat)
})
output$covid <- renderPlot({
ggplot(df_graf(), aes(antal_dagar, df_graf()[[input$var]], colour = land)) +
geom_line(size = 1.25) +
theme_Skane() +
labs(title = paste0("Coronalandskampen, ", input$stat),
x = "Antal dagar sedan 10:e dödsfallet",
y = as.name(input$var),
colour = NULL,
caption = "Source: European Centre for Disease Prevention and Control")
})
}
shinyApp(ui, server)

So basically, your question boils down to making sure that:
title = paste0("Coronalandskampen, ", input$stat)
returns the string "Coronalandskampen, France, The United Kingdom, Spain".
When running:
> paste0("Coronalandskampen, ", c("A", "B", "C", "D"))
[1] "Coronalandskampen, A" "Coronalandskampen, B"
[3] "Coronalandskampen, C" "Coronalandskampen, D"
We see that the result is a character vector with more than one element. The labsfunction uses only the first element of this vector. Therefore you need to build a single string.
Lets try this:
> paste0("Coronalandskampen, ", paste0(c("A", "B", "C", "D"), collapse = ", "))
[1] "Coronalandskampen, A, B, C, D"
So, in your code you can write:
title = paste0("Coronalandskampen, ", paste0(input$stat, collapse = ", "))

Related

Is there a way to create a network of word associations using a bi-partite network analysis in R?

I have a text file with words from historical accounts and I want to visualise the species and frequency of words associated with them.
So far I have tried using the following code with a txt file of all the historical documents in one doc but want to ask if there is specific formatting of a csv to then input into R for a bipartite network graph:
"""library(ggraph)
library(ggplot2)
library(dplyr)
library(pdftools)
library(tm)
library(readtext)
library(tidytext)
library(igraph)
library(tidyr)
library(FactoMineR)
library(factoextra)
library(flextable)
library(GGally)
library(ggdendro)
library(network)
library(Matrix)
library(quanteda)
library(stringr)
library(quanteda.textstats)
options(stringsAsFactors = F)
options(scipen = 999)
options(max.print=1000)
# Read in text--------
wordbase <- readtext("mq_bird_stories.txt")
# List of extra words to remove---------
extrawords <- c("the", "can", "get", "Ccchants", "make", "making", "house", "torn", "tree", "man", "however", "upon", "instructs", "wife", "coming","without", "mother", "versions","variant", "version", "thus", "got","throws", "are", "has", "already", "asks", "sacra", "can", "brings", "one", "look", "sees", "tonaheiee", "wants", "later",
"dont", "even", "may", "but", "will", "turn", "sing", "swallows", "alba", "gives", "find", "other","tonaheieee", "away","day","comes","another",
"much", "first", "but", "see", "new", "back","goes", "go","songs", "returns", "take","takes","come",
"many", "less", "now", "well", "taught", "like", "puts", "slits", "sends", "tell","tells","open","mentions",
"often", "every", "said", "two", "and", "handsome", "husband", "bring", "lives","gets", "von", "den", "steinen", "handy")
# Clean the data-------
darwin <- wordbase %>%
paste0(collapse = " ") %>%
stringr::str_squish() %>%
stringr::str_remove_all("\\(") %>%
stringr::str_remove_all("\\)") %>%
stringr::str_remove_all("!") %>%
stringr::str_remove_all(",") %>%
stringr::str_remove_all(";") %>%
stringr::str_remove_all("\\?") %>%
stringr::str_split(fixed(".")) %>%
unlist() %>%
tm :: removeWords(extrawords) %>%
paste0(collapse = " ")
# One method for calculating frequencies of bigrams------
# Process into a table of words
darwin_split <- darwin %>%
as_tibble() %>%
tidytext::unnest_tokens(words, value)
# Create data frame of bigrams-------
darwin_words <- darwin_split %>%
dplyr::rename(word1 = words) %>%
dplyr::mutate(word2 = c(word1[2:length(word1)], NA)) %>%
na.omit()
# Calculate frequency of bigrams-----
darwin2grams <- darwin_words %>%
dplyr::mutate(bigram = paste(word1, word2, sep = " ")) %>%
dplyr::group_by(bigram) %>%
dplyr::summarise(frequency = n()) %>%
dplyr::arrange(-frequency)
# Define stopwords
stps <- paste0(tm::stopwords(kind = "en"), collapse = "\\b|\\b")
# Remove stopwords from bigram table
darwin2grams_clean <- darwin2grams %>%
dplyr::filter(!str_detect(bigram, stps))
# Another method for calculating frequencies of bigrams
# Clean corpus
darwin_clean <- darwin %>%
stringr::str_to_title()
# Tokenize corpus----
darwin_tokzd <- quanteda::tokens(darwin_clean)
# Extract bigrams------
BiGrams <- darwin_tokzd %>%
quanteda::tokens_remove(stopwords("en")) %>%
quanteda::tokens_select(pattern = "^[A-Z]",
valuetype = "regex",
case_insensitive = FALSE,
padding = TRUE) %>%
quanteda.textstats::textstat_collocations(min_count = 1, tolower = FALSE)
# read in and process text
darwinsentences <- darwin %>%
stringr::str_squish() %>%
tokenizers::tokenize_sentences(.) %>%
unlist() %>%
stringr::str_remove_all("- ") %>%
stringr::str_replace_all("\\W", " ") %>%
stringr::str_squish()
# inspect data
head(darwinsentences)
darwincorpus <- Corpus(VectorSource(darwinsentences))
# clean corpus-----
darwincorpusclean <- darwincorpus %>%
tm::tm_map(removeNumbers) %>%
tm::tm_map(tolower) %>%
tm::tm_map(removeWords, stopwords()) %>%
tm::tm_map(removeWords, extrawords)
# create document term matrix
darwindtm <- DocumentTermMatrix(darwincorpusclean, control=list(bounds = list(global=c(1, Inf)), weighting = weightBin))
# convert dtm into sparse matrix
darwinsdtm <- Matrix::sparseMatrix(i = darwindtm$i, j = darwindtm$j,
x = darwindtm$v,
dims = c(darwindtm$nrow, darwindtm$ncol),
dimnames = dimnames(darwindtm))
# calculate co-occurrence counts
coocurrences <- t(darwinsdtm) %*% darwinsdtm
# convert into matrix
collocates <- as.matrix(coocurrences)
# inspect size of matrix
ncol(collocates)
#provide some summary stats
summary(rowSums(collocates))
#visualising collocations
# load function for co-occurrence calculation
source("https://slcladal.github.io/rscripts/calculateCoocStatistics.R")
# define term
coocTerm <- "pigeon"
# calculate co-occurrence statistics
coocs <- calculateCoocStatistics(coocTerm, darwinsdtm, measure="LOGLIK")
# inspect results
coocs[1:50]
coocdf <- coocs %>%
as.data.frame() %>%
dplyr::mutate(CollStrength = coocs,
Term = names(coocs)) %>%
dplyr::filter(CollStrength > 0)
###Make graph - visualize association strengths------
ggplot(coocdf, aes(x = reorder(Term, CollStrength, mean), y = CollStrength)) +
geom_point() +
coord_flip() +
theme_bw() +
labs(y = "")
##network
net = network::network(collocates_redux,
directed = FALSE,
ignore.eval = FALSE,
names.eval = "weights")
# vertex names
network.vertex.names(net) = rownames(collocates_redux)
# inspect object
net
ggnet2(net,label = TRUE,
label.size = 4,
alpha = 0.2,
size.cut = 3,
edge.alpha = 0.3) +
guides(color = FALSE, size = FALSE)"""
I'd suggest taking a look at the netCoin package. If you can transform your data into nodes and links data frames, then you can easily get a high quality network visualization:
#Example of links data frame
links <-
data.frame(
matrix(
c(
"Person A","Account 1", "not link",
"Person A","Account 2", "link",
"Person B","Account 2", "link",
"Person B","Account 3", "not link",
"Person B","Account 4", "link",
"Person C","Account 4", "link"
),
nrow = 6,
ncol = 3,
byrow = TRUE,
dimnames = list(NULL,
c("Source", "Target", "other_links_column"))
),
stringsAsFactors = FALSE
)
#Example of nodes data frame
nodes <-
data.frame(
matrix(
c(
"Person A","person",
"Person B","person",
"Person C","person",
"Account 1", "account",
"Account 2", "account",
"Account 3", "account",
"Account 4", "account"
),
nrow = 7,
ncol = 2,
byrow = TRUE,
dimnames = list(NULL,
c("name", "other_nodes_column"))
),
stringsAsFactors = FALSE
)
install.packages("netCoin") #may need to install the netCoin package
library(netCoin)
?netCoin #displays netCoin Help to see all the function options
graph_df <- netCoin(nodes = nodes, #Data frame of unique nodes and their attributes #Must contain name column
links = links, #Data frame of links and their attributes #Must contain Source and Target columns
cex = 1.25, #Font size
color = "other_nodes_column", #Column in node data frame to determine node color
shape = "other_nodes_column", #Column in node data frame to determine node shape
main = "This is the title of my visualization", #Visualization title
controls = 1:5, #Controls that will be shown in the visualization (maximum of 5)
dir = "folder-with-viz-output") #Output folder for the visualization #Entire folder should be exported as a zip file
plot(graph_df) #Command to display the visualization

ggplotly works in RStudio console but not rendering in shiny app

I am working on created a shiny app and I wrote a function to display a plotly. The function works fine and prints the plot when I run it in the console, but the ggplotly histogram will not render when I run the app. I do not receive any errors when running the function in the console nor when I try to run the app. The graphs just do not show up in the app. Here is the function, which I wrote in a helper file:
# making function to display simulated state-level pv2ps
pv2p_plot <- function(x) {
# filter based on input$state from ui.R
# getting text to specify the predicted pv2p and the chance of victory
pv2p <- sims %>%
drop_na() %>%
filter(state == x) %>%
mutate(d_pv2p = sim_dvotes_2020 / (sim_rvotes_2020 + sim_dvotes_2020),
r_pv2p = 1 - d_pv2p) %>%
summarise(d_pv2p = mean(d_pv2p) * 100,
r_pv2p = mean(r_pv2p) * 100)
win_prob <- sims %>%
mutate(biden_win = ifelse(sim_dvotes_2020 > sim_rvotes_2020, 1, 0)) %>%
group_by(state) %>%
summarise(pct_biden_win = mean(biden_win, na.rm = TRUE)) %>%
filter(pct_biden_win < 1 & pct_biden_win > 0) %>%
mutate(pct_trump_win = 1 - pct_biden_win) %>%
select(state, pct_biden_win, pct_trump_win) %>%
filter(state == x)
pv2p_lab <- paste0("Forecasted Two-Party Popular Vote: ", round(pv2p$d_pv2p, 2), "% for Biden and ", round(pv2p$r_pv2p, 2), "% for Trump")
win_lab <- paste0("Forecasted Probability of Electoral College Victory: ", round(win_prob$pct_biden_win * 100, 2), "% for Biden and ", round(win_prob$pct_trump_win * 100, 2), "% for Trump")
pv_plot <- sims %>%
filter(state == x) %>%
mutate(Democrat = sim_dvotes_2020 / (sim_dvotes_2020 + sim_rvotes_2020),
Republican = 1 - Democrat) %>%
pivot_longer(cols = c(Democrat, Republican), names_to = "party") %>%
ggplot(aes(value, fill = party)) +
geom_histogram(aes(y = after_stat(count / sum(count)),
text = paste0("Probability: ", round(after_stat(count / sum(count)), 5))), bins = 1000, alpha = 0.5, position = "identity") +
scale_fill_manual(breaks = c("Democrat", "Republican"),
labels = c("Biden", "Trump"),
values = c(muted("blue"), "red3")) +
labs(title = paste("Simulated Two-Party Popular Vote \nin", x),
x = "Predicted Share of the Two-Party Popular Vote",
y = "Probability",
fill = "Candidate",
subtitle = pv2p_lab) +
theme_hodp()
print(ggplotly(pv_plot, tooltip = "text"))
}
And this is my UI & server code from the app:
# loaded libraries, read in data, and created functions in other file to keep
# this script nice and clean
source("helper.R")
ui <- navbarPage(
# Application title
"Presidential Forecast in Retrospect",
tabPanel(
"About",
includeHTML(file.path("pages/about.html"))
),
navbarMenu("Forecast Simulations",
tabPanel("State-by-State Two-Party Popular Vote",
fluidPage(theme = "bootstrap.css",
tabsetPanel(
tabPanel("Estimated Vote Share",
selectInput("state",
"State:",
sims %>% pull(state) %>% unique() %>% sort()),
plotlyOutput("statesimPlotly")),
tabPanel("Probability of Victory",
selectInput("state_type",
"State Category:",
types %>% pull(type) %>% unique()),
plotlyOutput("statevictoryPlotly")
)
)
)
),
tabPanel("Predicted Vote Margin Map",
# creating this page to show the win margin
includeHTML(file.path("pages/margin_maps.html"))
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output, session) {
output$statesimPlotly <- renderPlotly({
# calling function that I defined at the top of the app
pv2p_plot(input$state)
})
output$statevictoryPlotly <- renderPlotly(
# calling function from helper to make this plot
state_win_probs(input$state_type)
)
}
# Run the application
shinyApp(ui = ui, server = server)
As I said above, the function works fine in my console. Most people who have had issues with this online are not using the proper output/render functions (e.g. using renderPlot instead of renderPlotly), but I am not seeing what is wrong with my code. Thanks in advance!

Formatting an ftable in R

I have the following 3 way table I created in R.
with(dataset, ftable(xtabs(count ~ dos + sex + edu)))
The output looks like
edu high low medium unknown
dos sex
five-to-ten-years female 247776 44916 127133 23793
male 225403 37858 147821 20383
five-years-or-less female 304851 58018 182152 33649
male 253977 55720 193621 28972
more-than-ten-years female 709303 452605 539403 165675
male 629162 309193 689299 121336
native-born female 1988476 1456792 2094297 502153
male 1411509 1197395 2790522 395953
unknown female 57974 75480 73204 593141
male 40176 57786 93108 605542
I want to rename the variables and format the table so that I can include it in a report. I know that I can use dnn to rename the variables, but are there any other recommendations to rename the variables? And to format the table (similar to using kable)?
You could convert the output to a text matrix using the following function, after which you can style with kable however you choose:
ftab_to_matrix <- function(ft)
{
row_vars <- attr(ft, "row.vars")
for(i in seq_along(row_vars)){
row_vars[[i]] <- c(names(row_vars[i]), row_vars[[i]])}
rowvar_widths <- sapply(row_vars, function(x) max(nchar(x))) + 1
col_vars <- attr(ft, "col.vars")
rowvar_widths <- c(1, cumsum(c(rowvar_widths, max(nchar(names(col_vars))))))
ft_text <- capture.output(print(ft))
row_cols <- sapply(seq_along(rowvar_widths)[-1], function(x)
substr(ft_text, rowvar_widths[x - 1], rowvar_widths[x]))
ft_text <- substr(ft_text, rowvar_widths[length(rowvar_widths)] + 2, 100)
ft_breaks <- c(1, cumsum(lapply(strsplit(ft_text[length(ft_text)], "\\d "),
function(x) nchar(x) + 2)[[1]]))
col_cols <- sapply(seq_along(ft_breaks)[-1], function(x)
substr(ft_text, ft_breaks[x - 1], ft_breaks[x]))
trimws(cbind(row_cols, col_cols))
}
So, for example, using my example data from your last question, you could do something like:
my_tab <- with(`3waydata`, ftable(xtabs(count ~ duration + sex + education)))
as_image(kable_styling(kable(ftab_to_df(my_tab))), file = "kable.png")
Might have been easier had you given the full picture when you asked your first question... You could use gt to make fancy tables for reports. This is an edited version more fully demonstrating some capabilities.
library(dplyr)
library(gt)
way3data <- data %>%
group_by(duration, education, sex) %>%
summarise(count = sum(number)) %>%
ungroup
# Reorder with select and Titlecase with stringr
longer <- tidyr::pivot_wider(way3data,
values_from = count,
names_from = "education") %>%
select(duration, sex, high, medium, low, unknown) %>%
rename_with(stringr::str_to_title)
# Demonstrating some of the features of gt
# obviously could have done some of this
# to the original dataframe
myresults <- longer %>%
group_by(Duration) %>%
gt(rowname_col = "Sex") %>%
row_group_order(
groups = c("native-born",
"more-than-ten-years",
"five-to-ten-years",
"five-years-or-less",
"unknown")
) %>%
tab_spanner(label = "Education",
columns = matches("High|Low|Medium|Unknown")) %>%
tab_stubhead(label = "Duration or something") %>%
tab_style(
style = cell_text(style = "oblique", weight = "bold"),
locations = cells_row_groups()) %>%
tab_style(
style = cell_text(align = "right", style = "italic", weight = "bold"),
locations = cells_column_labels(
columns = vars(High, Low, Medium, Unknown)
)) %>%
tab_style(
style = cell_text(align = "right", weight = "bold"),
locations = cells_stub()) %>%
tab_header(
title = "Fancy table of counts with Duration, Education and Gender") %>%
tab_source_note(md("More information is available at https://stackoverflow.com/questions/62284264."))
# myresults
# Can save in other formats including .rtf
myresults %>%
gtsave(
"tab_1.png", expand = 10
)
You can read about all the formatting choices here
Data compliments of Allan
set.seed(69)
data <- data.frame(education = sample(c("high","low","medium","unknown"), 600, T),
sex = rep(c("Male", "Female"), 300),
duration = sample(c("unknown", "native-born",
"five-years-or-less", "five-to-ten-years",
"more-than-ten-years"), 600, T),
number = rpois(600, 10))

Shiny App: Error in filter_impl: Result must have length 4090, not 0

Trying to run a shiny app, but keep getting the error: Error in filter_impl: Result must have length 4090, not 0
I've tried:
debugging by removing individual filters to try isolate the issue.
using dplyr::filter to force dplr's filter
ensured all filters are in a reactive function
checked whether it was an issue of sharing inputs between ui.R and server.r
checked whether it is caused by a previous df transformation.
Spent about 3 hours trying to find the cause, with no success.
Can you please help?
Server.R
rm(list = ls())
library(shiny)
library(tidyverse)
library(shiny)
library(ggplot2)
library(singer)
library(ggvis)
library(dplyr)
# Set Up DataFrames
data(package = "singer")
data(singer_locations)
sdf <- singer_locations %>% filter(year != 0) # filter out songs with missing years for simplicity
sdf %>% skim() %>% kable() # Check to see missing and incomplete values
sdf <- sdf %>% filter(complete.cases(.)) # filter out songs with missing observations for simplicity
sdf %>% skim() %>% kable() # Check to see if missing and incomplete values have been ignored
sdf <- sdf %>% select(
track_id, title, song_id, release, artist_id, artist_name, year, duration,
artist_hotttnesss, artist_familiarity, name, city, longitude, latitude
)
# add new columns with rounded data (for nicer graphs later)
sdf$latitude_rounded <- round(sdf$latitude, 0)
sdf$longitude_rounded <- round(sdf$longitude, 0)
sdf$duration_rounded <- round(sdf$duration, 0)
# Add song_popularity & very_popular_song columns
pops <- sdf$artist_hotttnesss + sdf$artist_familiarity
sdf$artist_popularity <- round(pops, 0)
sdf$very_popular_song <- round(sdf$artist_popularity)
sdf$very_popular_song[sdf$very_popular_song < 1] <- "No"
sdf$very_popular_song[sdf$very_popular_song >= 1] <- "Yes"
# Select() relevant variables so they can be passed into server below (without having to use df[,"VAR"])
songs_list <- sdf %>% select(
track_id, title, song_id, release, artist_id, artist_name, year, duration_rounded, duration,
artist_hotttnesss, artist_familiarity, name, city, latitude_rounded, longitude_rounded, longitude,
latitude, artist_popularity, very_popular_song
)
#axis_variables <- reactive({
axis_variables <- c(
"Length of Song (Seconds)" = "duration_rounded",
"Rating" = "artist_hotttnesss",
"Rating" = "artist_familiarity",
"Year" = "year",
"Popularity Rating" = "artist_popularity"
)
################################### SHINY SERVER #########################################
function(input, output) {
songs <- reactive({ # Create Reactive Filtering Component
duration_s <- input$duration_s
artist_hotttnesss_s <- input$artist_hotttnesss_s
artist_familiarity_s <- input$artist_familiarity_s
latitude_s <- input$latitude_s
longitude_s <- input$longitude_s
year_s <- input$year_s
artist_popularity_s <- input$artist_popularity_s
# Apply filters
songs_df <- songs_list %>%
dplyr::filter(
duration_rounded >= duration_s,
artist_hotttnesss >= artist_hotttnesss_s,
artist_familiarity >= artist_familiarity_s,
latitude_rounded >= latitude_s,
longitude_rounded >= longitude_s,
year >= year_s,
artist_popularity >= artist_popularity_s
) %>%
arrange(duration_rounded)
# filter by city option
if (input$city_in != "All") {
city_in_temp <- paste0("%", input$city_in, "%")
songs_df <- songs_df %>% dplyr::filter(songs_df$city %like% city_in_temp)
}
# filter by artist_name option
if (input$artist_name_in != "" && !is.null(input$artist_name_in)) {
artist_name_temp <- paste0("%", input$artist_name_in, "%")
songs_df <- songs_df %>% dplyr::filter(songs_df$artist_name %like% artist_name_temp)
}
songs_df <- as.data.frame(songs_df)
songs_df # return df
})
# search fuction
song_search <- function(s) {
if (is.null(s)) return(NULL)
if (is.null(s$track_id)) return(NULL)
# Isolate the given ID
songs_df <- isolate(songs())
temp_song <- songs_df[songs_df$track_id == s$track_id, ]
paste0("<b>", temp_song$artist_name, "</b><br>",
temp_song$year, "<br>",
"popularity ", format(temp_song$artist_popularity, big.mark = ",", scientific = FALSE)
)
}
# A reactive expression with the ggvis plot
vis <- reactive({
# setting variablex & variabley (input names are type str)
variablex <- prop("x", as.symbol(input$variablex))
variabley <- prop("y", as.symbol(input$variabley))
# Lables for axes
xvar_name <- names(axis_variables)[axis_variables == input$variablex]
yvar_name <- names(axis_variables)[axis_variables == input$variabley]
songs %>%
ggvis(x = variablex, y = variabley) %>%
layer_points(size := 50, size.hover := 200,
fillOpacity := 0.2, fillOpacity.hover := 0.5,
stroke = ~artist_popularity, key := ~artist_name) %>%
add_tooltip(song_search, "hover") %>%
add_axis("x", title = xvar_name) %>%
add_axis("y", title = yvar_name) %>%
add_legend("stroke", title = "Very Popular", values = c("Yes", "No")) %>%
scale_nominal("stroke", domain = c("Yes", "No"),
range = c("orange", "#aaa")) %>%
set_options(width = 500, height = 500)
})
vis %>% bind_shiny("plot1")
output$songs_selected <- renderText({ nrow(songs()) })
}
Ui.R
rm(list = ls())
library(tidyverse)
library(shiny)
library(ggplot2)
library(singer)
library(ggvis)
library(dplyr)
#axis_variables <- reactive({
axis_variables <- c(
"Length of Song (Seconds)" = "duration_rounded",
"Hotness Rating" = "artist_hotttnesss",
"Familiarity Rating" = "artist_familiarity",
"Year" = "year",
"Popularity Rating" = "artist_popularity"
)
# Define UI for application that draws a histogram
shinyUI(fluidPage(
shinythemes::themeSelector(),
titlePanel("Artist & Song Data"),
fluidRow(
column(3,
wellPanel(
h4("Filter By"),
# Slider Options for Data Exploration
sliderInput("duration_s", "Minimum duration of song (seconds)", 10, 500, 100, step = 10),
sliderInput("year_s", "Year released", 1900, 2018, value = c(1980, 2018)),
sliderInput("artist_hotttnesss_s", "Ranking / 10 for popularity", 0, 2, 0, step = 0.1),
sliderInput("artist_familiarity_s", "Ranking / 10 for familiarity", 0, 2, 0, step = 0.1),
sliderInput("artist_popularity", "Ranking / 10 for familiarity", 0, 2, 0, step = 0.1),
# Filter by custom input condition
textInput("city_in", "Name of the city"),
textInput("artist_name_in", "Artist's name contains (e.g Pink f)")
),
wellPanel(
selectInput("variablex", "X-axis", axis_variables, selected = "year"),
selectInput("variabley", "Y-axis", axis_variables, selected = "duration_rounded")
)
),
column(9,
ggvisOutput("plot1"),
wellPanel(
span("Degrees of Freedom",
textOutput("songs_selected")
)
)
)
)
It looks like you are filtering using data created by input$XXX. Try to put req(input$XXX, req(input$YYY, ...) at the beginning of your reactive element(s).
Also read this tweet about starting with rm(list = ls()).

Barplot stops functioning when adding a key in ggvis (needed for tooltip)

I want to have a tooltip on my bar graph that shows detailed info about a customer when hovered over. The problem is that without a defined key the tooltip does not function and with a defined key the barplot does not function properly anymore. Here is the data I used:
CustomerData:
id;CustomerID;CLV;Gender;Channel;Age
1;1;300;male;facebook;24
2;2;2000;female;google ads;34
3;3;500;female;other;43
4;4;1300;male;google ads;34
5;5;100;male;other;46
6;6;400;female;other;32
7;7;600;female;google ads;43
8;8;1000;male;other;46
9;9;200;female;other;75
10;10;1700;male;google ads;35
11;11;1600;female;google ads;23
12;12;800;female;other;54
13;13;400;female;other;34
14;14;700;male;google ads;42
15;15;500;male;facebook;18
16;16;200;male;other;42
17;17;1900;male;google ads;46
18;18;400;female;other;23
19;19;600;male;other;45
20;20;200;female;other;42
21;21;1400;male;facebook;57
22;22;1200;female;facebook;54
Ui Code:
#this is the ui code
shinyUI(pageWithSidebar(
headerPanel("CLV Reporting"),
sidebarPanel(
navbarMenu(
checkboxGroupInput("gender", 'Gender:',
c("female" = "female",
"male" = "male"))),
navbarMenu(
checkboxGroupInput("channel", 'Channel:',
c("Facebook" = "facebook",
"Google Ads" = "google ads",
"Other" = "other"))),
navbarMenu(
sliderInput("age", "Age Range:",
min = 0, max = 100, value = c(20,50)))
),
mainPanel(
ggvisOutput("barplot"),
textOutput("mean"),
textOutput("price")
)
))
Server Code:
#this is the server code
library(ggvis)
library(dplyr)
library(ggplot2)
library(shiny)
shinyServer(function(input, output, session) {
report <- reactive({
gender <- input$gender
channel <- input$channel
minage <- input$age[1]
maxage <- input$age[2]
rep <- CustomerData %>%
filter(
Gender %in% gender,
Channel %in% channel,
Age >= minage,
Age <= maxage
)
})
#tooltip input
Customer_tooltip <- function (x) {
if (is.null(x)) return(NULL)
if (is.null(x$id)) return(NULL)
CustomerData <- isolate(report())
customer <- CustomerData[CustomerData$id == x$id, ]
paste0("<b>", "Customer ID: ", customer$CustomerID, "</b><br>",
"Gender: ", customer$Gender, "</b><br>",
"Channel: ", customer$Channel, "</b><br>",
"Age: ", customer$Age, "<br>",
"CLV: $", format(customer$CLV, big.mark = "'", scientific = FALSE)
)
}
# output
vis <- reactive({
report %>%
ggvis(x = ~factor(CustomerID), y = ~CLV) %>%
layer_bars(fillOpacity := 0.5, fillOpacity.hover := 1, key := ~id) %>%
add_tooltip(Customer_tooltip, "hover") %>%
add_axis("x", title = "Customer") %>%
add_axis("y", title = "CLV", title_offset = 60) %>%
set_options(width = 500, height = 300)
})
vis %>% bind_shiny("barplot")
output$mean <- renderText({
m <- report()
if (nrow(m) != 0) {paste("The mean CLV of the selected customers is: $", round(mean(m$CLV)))}
else {"There are no customers with these specifications."}
})
output$price <- renderText({
m <- report()
if (nrow(m) != 0) {paste("We recommend to spend $", round(mean(m$CLV)/12)*nrow(m), " on retaining these customers.")}
else {""}
})
})
I added the id column because I thought this could solve the problem (using a key which is not used by anything else in the code). Just in case you wondered why there were two variables with the exact same values ;)
(edit) I uploaded the newest version to gisthub:
https://gist.github.com/anonymous/f04325078f9c0656ab72
packages needed: shiny, ggvis, dplyr and ggplot2

Resources