How to change fill using handle_click? - r

I have a bar chart like this
iris %>% ggvis(~Species, ~Petal.Width)
and I would like to use handle_click() to change the fill of a bar to red when one is clicked. For example, if I clicked on versicolor, it should look like this
iris %>% ggvis(~Species, ~Petal.Width) %>% layer_bars(fill=~Species) %>% scale_nominal("fill", range = c("#333333","red", "#333333"))
I know I need to handle the click event, but I wasn't able to understand how by looking at the documentation. I have started with this, but I have no clue how to set up the barRed():
barRed <- function(data, location, session, ...) {
}
iris %>% ggvis(~Species, ~Petal.Width) %>%
handle_click(on_click=barRed)

Related

Altering Linewidth and Color for LineString Objects in Mapview

I'm working with reefs across a large area and trying to visualize them quickly such that I can pick a smaller subset to work on initially. To do this, I have taken my spatial points, transformed them to LineString to make the mapping quicker and then used mapview to display them. The code I have is below:
data_as_sf %>%
filter(reef_name %in% subgroup) %>%
group_by(.dots=c("reef_name", "reef_section")) %>%
summarize() %>%
st_cast("LINESTRING") %>%
mapview()
A zoomed in sample of the mapview generated is here:
If anyone can provide advice such that I can
make the lines bigger/thicker so they are more easily seen when
zoomed out, and
have the lines colored by the factor "reef_name"
it would really help.
As answered in the comments by TimSalabim, have now updated the code to be
data_as_sf %>%
filter(reef_name %in% subgroup) %>%
group_by(.dots=c("reef_name", "reef_section")) %>%
summarize() %>%
st_cast("LINESTRING") %>%
mapview(lwd = 3, zcol = "reef_name")
which works just right.

How to add tooltip with shares to ggvis histogram?

I would like to create an interactive histogram which gives information about the bins by hover. This thread gives answer to how to add tooltip with count numbers.
library("ggvis")
cocaine %>%
ggvis(x = ~weight) %>%
layer_histograms() %>%
add_tooltip(function(df) (paste("count:", df$stack_upr_ - df$stack_lwr_)))
How can I add the share of each bin as well? I should somehow add nrow(cocaine) to ggvis and create the shares from count but I did not succeed on how to achieve that (tried to take the suggestions of this post but apparently that solves a different problem).
You could do something like this I imagine:
cocaine %>%
ggvis(x = ~weight) %>%
layer_histograms() %>%
add_tooltip(function(df) paste("count:", df$stack_upr_, 'share:',
format(df$stack_upr_/nrow(cocaine), digits=2)))
This will show both the share and the bin number.
Also, as a side note you do not need df$stack_upr_ - df$stack_lwr_ because df$stack_lwr_ will be zero. Just df$stack_upr_ will do.

ggvis graphic with group selection

I want to use ggvis for data exploration (because I am familiar with ggplot2), and it would be of great help, due to many groups in my data sets, to be able to select and unselect groups to make different specific (data) comparisons.
set.seed(10)
dat <- data.frame(x=c(1:3,1:3),y=rnorm(6),groups=factor(rep(1:2,each=3)))
library(ggvis)
dat %>% ggvis(~x, ~y) %>% layer_points(fill=~groups)
# i know this example does not work - but is that possible somehow?
dat %>% ggvis(~x, ~y) %>% layer_points(fill=input_checkbox(~groups))
What I want at the end, is a graphic with which I can select a subset of groups by using radio buttons (for example).
Is there any way to do that?
Thank you!
From the documentation
Limitations
Currently, interactive inputs can only be used in two places:
as arguments to transforms: layer_smooths(span = input_slider(0, 1))
as properties: props(size = input_slider(10, 1000))
This means that interactive inputs can only modify the data, not the
underlying plot specification. In other words, with only basic
interactivity there’s no way to add or remove layers, or switch
between different datasets. This is a reasonable limitation because if
you’re doing exploration you can always create a new ggvis with R
code, or if you’re polishing a plot for presentation, you can embed it
in a Shiny app and gain full control over the plot.
For simple data exploration, one idea could be to use filter():
set.seed(10)
dat <- data.frame(x = c(1:5,1:5,1:5),
y = rnorm(15), groups = factor(rep(1:5,each=3)))
Note: I edited your initial dataset to illustrate the concept with more groups
library(dplyr)
library(ggvis)
dat %>% ggvis(~x, ~y) %>% layer_points(fill = ~groups)
You could pass the arguments (either manually directly in your R code or with your radio buttons in a Shiny app) to filter() to isolate specific groups:
dat %>%
filter(groups == 1 | groups == 3) %>%
ggvis(~x, ~y) %>% layer_points(fill = ~groups)

ggvis Map & Tooltips

I am trying to layer on tooltips to a map of the US, but wherever I hover... it displays the same data. In addition, the data is wrong. I'm thinking that it is passing through the factor values and not the character value. I tried taking tips from the movie explorer example - http://shiny.rstudio.com/gallery/movie-explorer.html - but, it's not working as I hoped. Any hints or clues I should look into?
Update: I've determined that you can only pass through arguments that are being called into the ggvis function. So, if my tooltip function included region, long, & lat, all of them would appear in the tooltip. Since Population and Income do not appear anywhere in the function, it is not passing them through. I'm still lost on how to proceed, but any ideas would be awesome! :)
library(ggplot2)
library(shiny)
library(ggvis)
library(dplyr)
shinyApp(
ui = fluidPage(
#numericInput("n", "n", 1),
ggvisOutput("map")
),
server = function(input, output) {
statesData <- reactive({
states <- data.frame(state.x77)
states$region <- row.names(state.x77) %>% tolower
row.names(states) <- NULL
all_states <- map_data("state") %>%
mutate(region = tolower(region)) %>%
left_join(states)
all_states_unique <- all_states %>%
select(region, Population, Income, Illiteracy, Life.Exp, Murder, HS.Grad, Frost, Area) %>%
unique
states_tooltip <- function(x) {
if (is.null(x)) return(NULL)
if (is.null(x$region)) return(NULL)
# Pick out the movie with this ID
allStates <- isolate(all_states_unique)
state <- allStates[allStates$region == x$region, ]
paste0("<b>", state$region, "</b><br>",
state$Population, "<br>",
state$Income
)
}
all_states %>%
arrange(group, order) %>%
ggvis(x = ~long, y = ~lat) %>%
layer_paths(fill = ~region, stroke := .2) %>%
add_tooltip(states_tooltip, "hover")
})
statesData %>% bind_shiny('map')
}
)
Add an index to the dataframe you want to pull the tooltip data from:
state$id <- 1:nrow(state)
ggvis takes a "key" argument to facilitate this kind of tooltip:
ggvis(x = ~long, y = ~lat, key := ~id) %>%
I tried figuring out that movie example and didn't find it very helpful. This always works for me:
add_tooltip(function(x) {
row <- state[state$id == x$key,]
paste0("<b>", row[,"region"], "</b><br>",
row[,"Population"], "<br>",
row[,"Income"]
)})
As for the issue w/ the tooltip always coming up the same, I don't know for sure but think it's due to the order of your layers in the ggvis command. Had a similar problem where I had some polygons layered on top of a scatterplot. It kept trying to draw the tooltip for the polygons (which covered the whole chart) when what I wanted was the individual points to display the tooltip. By reversing their order in the ggvis command (ie layer_points() %>% layer_shapes()) I got it to work.
I realise this is quite late but for future reference and others that stumble across this page. If your dataframe has been converted using fortify and has the group variable then this may be equivalent to the State level. Group can then be used to filter for the tooltip as it is in the ggvis command. That then allowed me to gain access to other variables I wanted.
In my problem I couldn't use the key solution because I was creating the plot to react to numerous years. So to change what you have above states_tooltip would become:
states_tooltip <- function(x){
row <- allstates[allstates$group==x$group,] %>%
select(region, Population, Income) %>% unique
paste0("<b>", row[,"region"], "</b><br>",
row[,"Population"], "<br>",
row[,"Income"]
)})

Position_fill function equivalent in ggvis?

Trying to replicate the ggplot function position="fill" in ggvis. I use this handy function all the time in the presentation of results. Reproducible example successfully performed in ggplot2 + the ggvis code. Can it be done using the scale_numeric function?
library(ggplot2)
p <- ggplot(mtcars, aes(x=factor(cyl), fill=factor(vs)))
p+geom_bar()
p+geom_bar(position="fill")
library(ggvis)
q <- mtcars %>%
ggvis(~factor(cyl), fill = ~factor(vs))%>%
layer_bars()
# Something like this?
q %>% scale_numeric("y", domain = c(0,1))
I think that to do this sort of thing with ggvis you have to do the heavy data reshaping lifting before sending it to ggvis. ggplot2's geom_bar handily does a lot of calculations (counting things up, weighting them, etc) for you that you need to do explicitly yourself in ggvis. So try something like the below (there may be more elegant ways):
mtcars %>%
mutate(cyl=factor(cyl), vs=as.factor(vs)) %>%
group_by(cyl, vs) %>%
summarise(count=length(mpg)) %>%
group_by(cyl) %>%
mutate(proportion = count / sum(count)) %>%
ggvis(x= ~cyl, y = ~proportion, fill = ~vs) %>%
layer_bars()

Resources