aggregating functions in ggvis add_tooltip - r

I am trying to add the frequency of each bar into a tooltip and am having issues. I attempted to use a group_by unsuccessfully. The tooltip returns a 4 for each tooltip for each bar.
mtcars %>%
ggvis(x = ~cyl) %>%
layer_histograms(fill="sky blue"
, fillOpacity:=.7
, fillOpacity.hover:=.9) %>%
group_by(cyl) %>%
add_tooltip(function(x) length(x))
This method has the same issue. It returns a 4 for each bar...
Freq <- function(x) {
paste0("Frequency: ", length(x))
}
mtcars %>%
ggvis(x = ~cyl) %>%
layer_histograms(fill="sky blue"
, fillOpacity:=.7
, fillOpacity.hover:=.9) %>%
group_by(cyl) %>%
add_tooltip(Freq)

To just quickly enable tool-tips with all values you can create a function all_values and add those.
all_values <- function(x) {
if(is.null(x)) return(NULL)
paste0(names(x), ": ", format(x), collapse = "<br />")
}
mtcars %>% group_by(cyl) %>%
ggvis(x = ~cyl) %>%
layer_histograms(fill="sky blue"
, fillOpacity:=.7
, fillOpacity.hover:=.9) %>%
add_tooltip(all_values, "hover")
You can use that information to piece together a function for what you actually want to show. In this case, just the upper value of the piece of the stacked bar chart.
mtcars %>% group_by(cyl) %>%
ggvis(x = ~cyl) %>%
layer_histograms(fill="sky blue"
, fillOpacity:=.7
, fillOpacity.hover:=.9) %>%
add_tooltip(function(df) (df$stack_upr_),"hover")

Related

What is a good approach to add sparkline chart to an R gt table

I am trying to use R sparkline with gt. My question is very similar to this one Is it possible to use sparkline with gt?, but on top of simply using sparkline with gt as in the referenced question, I am trying to use it as part of the summary row. Below is the picture of what I have achieved so far. Here are my two questions:
How can I remove the two grey lines that are printed as part of the sparkline chart in the summary row?
Is there a better way to add sparkline to the summary row of a gt table?
library(tidyverse)
library(sparkline)
library(gt)
# toy data
df <- tibble(
name = rep(c("A", "B"), each = 20),
value = runif(40, min = -10, max = 10) %>% cumsum()
) %>%
group_by(name) %>%
mutate(
index = row_number()
) %>% ungroup()
# preparing the data for the standard sparkline
regular_sparkline_df <- df %>%
group_by(name) %>%
summarise(
chart = spk_chr(
value,
type="line"
)
)
# here I try to prepare the data for the summary row by getting the whole gt table and then removing the header
summary_row_sparkline_df <- df %>%
group_by(index) %>%
summarise(value = sum(value)) %>% ungroup() %>%
summarise(
chart = spk_chr(
value,
type="line"
)
) %>%
gt() %>%
fmt_markdown(columns = vars(chart)) %>%
gt:::as.tags.gt_tbl() %>%
htmltools::attachDependencies(htmlwidgets::getDependency("sparkline")) %>%
as.character() %>%
gsub('<thead.+</thead>', "", .) # removing the header of the table
# building the html and adding dependencies
p_html <- regular_sparkline_df %>%
gt() %>%
fmt_markdown(columns = vars(chart)) %>%
grand_summary_rows(
columns = "chart",
fns = list(Total = ~as.character(summary_row_sparkline_df)),
formatter = fmt_markdown
) %>%
gt:::as.tags.gt_tbl() %>%
htmltools::attachDependencies(htmlwidgets::getDependency("sparkline"))
# seeing the table in the RStudio
print(p_html, browse = interactive())

Arrange gt tables side by side or in a grid or table of tables

I'd like to generate a set of gt table objects in a grid or side-by-side. For example, the code below uses the group_by argument to vertically separate them. But what if I wanted them separated side-by-side?
mtcars2 <-
mtcars %>%
mutate(good_mpg = ifelse(mpg > 20, "Good mileage", "Bad mileage"),
car_name = row.names(.))
mtcars2 %>%
group_by(good_mpg) %>%
slice_max(order_by = hp, n=5) %>%
arrange(hp) %>%
select(car_name, hp) %>%
gt() %>%
data_color(columns = c("hp"),
colors = col_numeric(palette = "Blues",
domain = c(0, 400)))
You can do this by using as_raw_html() for the internal tables, and fmt_markdown(columns = TRUE) in the top-level table.
hp_table <- function(x){
gt(x) %>%
data_color(columns = c("hp"),
colors = col_numeric(palette = "Blues",
domain = c(0, 400))) %>%
tab_options(column_labels.hidden = TRUE) %>%
as_raw_html() # return as html
}
good_mpg_table <-
mtcars %>%
mutate(good_mpg = ifelse(mpg > 20, "Good mileage", "Bad mileage"),
car_name = row.names(.)) %>%
filter(good_mpg == "Good mileage") %>%
head(5) %>%
arrange(hp) %>%
select(car_name, hp) %>%
hp_table()
bad_mpg_table <-
filter(good_mpg == "Bad mileage") %>%
head(5) %>%
arrange(hp) %>%
select(car_name, hp) %>%
hp_table()
data_tables <- data.frame(good_table = good_mpg_table,
bad_table = bad_mpg_table)
data_tables %>%
gt() %>%
fmt_markdown(columns = TRUE) %>% #render cell contents as html
cols_label(good_table = "High mileage",
bad_table = "Low mileage")
#Daniel, thank you for sharing this! This can come in handy.
To make the code a little bit more compact you could use group_map (or do) to generate the two tables within the dplyr workflow, then join them as you did:
library(dplyr)
library(gt)
library(scales)
hp_table <- function(x){
gt(x) %>%
data_color(columns="hp",
colors=col_numeric(palette="Blues", c(0, 400))) %>%
tab_options(column_labels.hidden = TRUE) %>%
as_raw_html()
}
mtcars %>%
mutate(good_mpg = ifelse(mpg > 20, "Good mileage", "Bad mileage"),
car_name = row.names(.)) %>%
arrange(hp) %>%
group_by(relevel(factor(good_mpg), "Good mileage")) %>%
slice_head(n=5) %>%
select(car_name, hp) %>%
group_map(~ hp_table(.x)) %>%
data.frame(.) %>%
setNames(., c("High mileage", "Low mileage")) %>%
gt() %>%
fmt_markdown(columns = TRUE)

Multiple line graphs in ggvis using for loop

I am trying to create multiple line graphs using ggvis. I am able to plot multiple lines but I am unable to add tooltip for these lines. I need to show the x and y value when I hover the mouse on the lines. I also am unable to add points to the lines in the for loop.
Below is a simplified example I am working with. column "c1" is the x values and columns "c2", "c3" and "c4" are to be plotted(lines with points and tooltip)
Screenshot of the plot
mydf <- data.frame(c(1:10),c(11:20), c(21:30), c(31:40))
v <- c("c1","c2","c3", "c4")
names(mydf) <- v
myggv <- mydf %>% ggvis(x = ~c1, y = ~c2) %>% layer_lines() %>% layer_points() %>% add_tooltip( function(mydf){paste0("x:",mydf$c1,"<br>","y:",mydf$c2)}, "hover")
for(r in v[2:length(v)]){
myggv <- (myggv %>% layer_paths(x = ~c1, y = as.name(r)) %>% layer_points()
%>% add_tooltip( function(mydf){paste0("x:",mydf$c1,"<br>","y:",mydf[,r] )}, "hover"))
}
Thanks
The best approach here is to not use a for loop. I mean, you can, but it's not the way ggvis approaches things. Also I can't get the tooltip to work in the loop (it gives the only the correct result for the last added line. But here is how I would do it anway:
mydf <- data.frame(c1 = c(1:10),
c2 = c(11:20),
c3 = c(21:30),
c4 = c(31:40))
myggv <- ggvis(mydf)
for (r in names(mydf)[-1]) {
myggv <- (myggv %>%
layer_paths(x = ~c1, y = as.name(r)) %>%
layer_points(x = ~c1, y = as.name(r)) %>%
add_tooltip(function(mydf) {
paste0("x:", mydf[[1]], "<br>", "y:", mydf[[r]])}, "hover"))
}
The nicer way is to restructure your data, and then use group_by to create seperate lines. As an added benefit, this is perhaps nicer to read. This way your tooltips also work:
mydf2 <- tidyr::gather(mydf, 'var', 'val', -c1)
myggv2 <- mydf2 %>%
ggvis(x = ~c1, y = ~val) %>%
layer_points() %>%
add_tooltip(function(d) { paste0("x:", d$c1, "<br>", "y:", d$val) }, "hover") %>%
group_by(var) %>%
layer_paths()
You might want to use layer_lines() instead of layer_paths().

How can I map numeric values to the fill attribute of a map in ggvis?

I am using the following code to draw a map in ggvis
First I download the json file with the coordinates
us <- readOGR("http://eric.clst.org/wupl/Stuff/gz_2010_us_040_00_20m.json", "OGRGeoJSON")
Then I fortify the dataset
map <- ggplot2::fortify(us)
And I create a dataset of the values that I want to represent in the map, standardized from 0 to 1:
value <- data_frame(stateName=us$NAME, value=seq(1:52)/52)
Lastly, I (succesfully) draw my map:
tbl_df(map)%>%
filter(long>-130 & long<0) %>%
filter(lat>20) %>%
ggvis(~long, ~lat) %>%
group_by(group, id) %>%
layer_paths(strokeOpacity:=0.5, stroke:="#7f7f7f", fill:="#cc0000") %>%
scale_numeric("y", domain=c(24,50)) %>%
scale_numeric("x", domain=c(-126,-72)) %>%
hide_legend("fill") %>%
hide_axis("x") %>%
hide_axis("y") %>%
set_options(width=400, height=600, keep_aspect=TRUE)
However, because the all process is a bit black-boxy to me, I don't know how to map the values from the dataset value to the ggvis map efficiently. I would like to use a color gradient on the fill attribute, but even playing with the transparency would be ok.
I guess I should tell to fortify() to keep the us$NAME, but how?
Are you looking for something like that:
us#data$id = rownames(us#data)
us_class = fortify(us, region="id")
us.df = join(us_class, us#data, by="id")
value <- data_frame(NAME=us$NAME, value=seq(1:52)/52)
us.df <- join(us.df, value)
tbl_df(us.df)%>%
filter(long>-130 & long<0) %>%
filter(lat>20) %>%
ggvis(~long, ~lat) %>%
group_by(group, id) %>%
layer_paths(strokeOpacity:=0.5, stroke:="#7f7f7f", fill:="#cc0000") %>%
scale_numeric("y", domain=c(24,50)) %>%
scale_numeric("x", domain=c(-126,-72)) %>%
hide_legend("fill") %>%
hide_axis("x") %>%
hide_axis("y") %>%
set_options(width=400, height=600, keep_aspect=TRUE) %>%
layer_paths(fill= ~value)

Disappearing values in ggvis when using tooltip on grouped data

This works fine
library(dplyr)
library(ggvis)
years <- as.factor(c(2013,2013,2014,2014,2015,2015))
months <- c(1,2,1,2,1,2)
values <- c(3,2,4,6,5,1)
df <- data.frame(years,months,values)
df %>%
group_by(years) %>%
ggvis(~months, ~values) %>%
layer_points( fill = ~years)
However, when I add a tooltip the points all appear momentarily but only the 2015 values remain
df <- cbind(df, id = seq_len(nrow(df)))
all_values <- function(x) {
if(is.null(x)) return(NULL)
row <- df[df$id == x$id,]
paste0(names(row),": ",format(row), collapse = "<br />")
}
df %>%
group_by(years) %>%
ggvis(~months, ~values, key:= ~id) %>%
layer_points( fill = ~years) %>%
add_tooltip(all_values, "hover")
Probably some simple error, but any help appreciated
cheers
At the moment, trying to add a tooltip specific to a row when the data are grouped doesn't seem to work. This makes some sense, actually, as the grouping implies that you may want info by group.
You don't need grouping in your layer_points example at all, but you would need it if you wanted lines between the points for specific years as well as points. If this is what you wanted, you'd group the dataset after you add the points, and put key in layer_points instead of in the overall ggvis.
df %>%
ggvis(~months, ~values) %>%
layer_points( fill = ~years, key:= ~id) %>%
add_tooltip(all_values, "hover") %>%
group_by(years) %>%
layer_lines(stroke = ~years, strokeWidth := 2)
This isn't totally ideal, because the tooltip still shows up for the lines even though lines don't have unique id data associated with them. To change this, make a small change to your tooltip function to check just if the id variable is NULL rather than the whole dataset from ggvis.
all_values = function(x) {
if(is.null(x$id)) return(NULL)
row <- df[df$id == x$id,]
paste0(names(row),": ",format(row), collapse = "<br />")
}
You can add a tooltip at the group level, but you'll need to figure out what sort of summary info you want to display. In the function for the tooltip you will be working with the grouping variable instead of id.
For example, you could just show all values associated with the group. The way I've set this up you'll need to click on the line to see the group info:
group_values1 = function(x) {
if(is.null(x)) return(NULL)
group = df[df$years == unique(x$years),]
paste0(names(group), ": ", format(group), collapse = "<br />")
}
df %>%
ggvis(~months, ~values) %>%
layer_points( fill = ~years, key:= ~id) %>%
add_tooltip(all_values, "hover") %>%
group_by(years) %>%
layer_lines(stroke = ~years, strokeWidth := 2) %>%
add_tooltip(group_values1, "click")
You may want to show summary information, instead. In this example, I'll display the overall change in values and how many months passed in the tooltip. I make the summary dataset with functions from dplyr.
group_values2 = function(x) {
if(is.null(x)) return(NULL)
group = df[df$years == unique(x$years),]
groupval = group %>% group_by(years) %>%
summarise(`Change in value` = max(values) - min(values),
`Months Passed` = max(months) - min(months))
paste0(names(groupval), ": ", format(groupval), collapse = "<br />")
}
df %>%
ggvis(~months, ~values) %>%
layer_points( fill = ~years, key:= ~id) %>%
add_tooltip(all_values, "hover") %>%
group_by(years) %>%
layer_lines(stroke = ~years, strokeWidth := 2) %>%
add_tooltip(group_values2, "click")
The problem lies in you putting group_by before ggvis and calling add_tooltip afterwards. Just put group_by part after ggvis call
df %>%
ggvis(~months, ~values, key:= ~id) %>%
group_by(years) %>%
layer_points( fill = ~years) %>%
add_tooltip(all_values, "hover")
no idea why it happens though

Resources