Multiple plots from multiple data frames using ggvis in shiny in R - r

How do I plot multiple series from different data frames, with different numbers of rows on one ggvis plot?
shinyServer(function(input, output, session) {
vis1 <- reactive({
df2 <-data.frame(csv1)
df3 <- data.frame(csv2)
long2 <- array()
matrix2<-data.frame(Col1,Col2,Col3,Col4)
matrix2$long2 = as.character(paste0("Col3: ",Col3,", Col4: ",Col4))
matrix2 # What does this line do?
})
vis1 %>%
ggvis(x = ~Col1, y = ~Col2,fill = ~Col4, key:= ~long2) %>%
layer_points() %>%
add_axis("x", title = "Col1") %>%
scale_numeric("x", domain = c(0, 130), nice = FALSE, clamp = TRUE)%>%
add_axis("y", title = "Col2") %>%
scale_numeric("y", domain = c(0, 8000), nice = FALSE, clamp = TRUE)%>%
add_tooltip(function(matrix2){
paste0("Col2: ", matrix2$Col2, "<br>", "Col1: ", matrix2$Col1, "<br>", " ", as.character(matrix2$long2))
}, "hover") %>%
layer_paths(data = df2, x = ~Col1,y = ~Col2,fill:="green") %>%
bind_shiny("plot_col2")#,"plot_ui_col2")
output$matrix2_table <- renderTable({
vis1()[,c("Col1","Col2","Col3","Col4")]
})
This is most of the server.R code, with ui.R code that works fine with one series plotted on these axes.
But trying to put the data from two data frames on these axes just returns
"Error in add_data(vis, data, data_name) : object 'df2' not found"
Doesn't even get to df3.
How do I get it to recognise df2, then use that data to plot the second series?
I get that plotting two series from the same data frame is done like this:
df %>% ggvis(~x,~y) layer_points() %>%
df %>% layer_points(~x,~y1)
There abouts, but how is it done with different numbers of points and from different data frames?
Thank you.

I put everything in the same data frame, in the same columns, just added more rows, also added a colours column, so they would be plotted in different colours.
The first thing to do was to make a much larger data frame in the unnamed function section at the top (only executes once).

Related

R: How to create a Drilldown Highchart using loops

when doing a job I have found a problem that I don't know how to solve.
I have a data frame that has 2 columns:
date
value
And it has a total of 1303 rows.
For each date there are 12 values (1 for each month), except in the last year that only has 7
The work I have to do would be to create a 'drilldown' style chart using the 'highcharter' library. The problem is that I don't know how to do it efficiently.
The solution that comes to my mind is not very efficient, below I show my solution so you can see what I mean.
dataframe
# Load packages
library(tidyverse)
library(highcharter)
library(lubridate)
# Load dataset
df <- read.csv('example.csv')
# Prepare df to use
dfDD <- tibble(name = year(df$date),
y = round(df$value, digits = 2),
drilldown = name)
# Create a data frame to use in 'drilldown' (for each year)
df1913 <- df %>%
filter(year(date) == 1913) %>%
data.frame()
df1914 <- df %>%
filter(year(date) == 1914) %>%
data.frame()
# Create a drilldown chart using Highcharter library
highchart() %>%
hc_chart(type = "column") %>%
hc_title(text = "Example Drilldown") %>%
hc_xAxis(type = "category") %>%
hc_legend(enabled = FALSE) %>%
hc_plotOptions(series = list(boderWidth = 2,
dataLabels = list(enabled = TRUE))) %>%
hc_add_series(data = dfDD,
name = "Mean",
colorByPoint = TRUE) %>%
hc_drilldown(allowPointDrilldown = TRUE,
series = list(list(id = 1913,
data = list_parse2(df1913)),
list(id = 1914,
data = list_parse2(df1914))))
Seeing my solution for the first time, I realized that in order to complete the graph I would have to create a subset of values for each year. Having realized that I tried to find a more efficient solution using a 'for loop' but so far I can't get it to work.
Is there a more efficient way to create this graph using a 'loop'!?
If it can be done in another way than using loops, I would also like to know.
Thank you for reading my question and I hope I explained myself well.
Using split and purrr::imap you could split your data by years and loop over the resulting list to convert your data to the nested list object required by hc_drilldown. Note: It's important to make the id a numeric and to pass a unnamed list.
library(tidyverse)
library(highcharter)
library(lubridate)
series <- split(df, year(df$date)) %>%
purrr::imap(function(x, y) list(id = as.numeric(y), data = list_parse2(x)))
# Unname list
names(series) <- NULL
highchart() %>%
hc_chart(type = "column") %>%
hc_title(text = "Example Drilldown") %>%
hc_xAxis(type = "category") %>%
hc_legend(enabled = FALSE) %>%
hc_plotOptions(series = list(boderWidth = 2,
dataLabels = list(enabled = TRUE))) %>%
hc_add_series(data = dfDD,
name = "Mean",
colorByPoint = TRUE) %>%
hc_drilldown(allowPointDrilldown = TRUE,
series = series)

Save local ggplot graphics and use in reactable table

I'd like to generate small ggplot graphics and use them inline in a reactable. I can generate the plots needed (1 per row), but when inserting them into the table, they come up as broken images. I imagine it has something to do with the file paths?
Note: This will ultimately be used in a shiny app where the graphics are generated dynamically. I am doing this in reactable because I plan to combine this with the expandable rows feature.
Here is some reproducible code
library(tidyverse)
library(palmerpenguins)
library(reactable)
#get list of species names
species <- penguins %>% select(species ) %>%
distinct() %>% pull()
# make a simple df
plot_data <- penguins %>%
group_by(species) %>%
summarize(mean = mean(bill_length_mm, na.rm=T))
# for loop to generate and save plots
for(i in species){
tmp_plot <-
plot_data %>%
filter(species == i) %>%
ggplot(aes(y=species, x=mean))+
geom_col()+
theme_void()
file_name <- i %>% janitor::make_clean_names()
ggsave(plot = tmp_plot,
filename = paste0("plots/",file_name,".png"),
width=4,
height=.5)
}
#make a table
species %>%
as.data.frame() %>%
rename("species" = 1) %>%
mutate(plot = paste0("<img src='plots/", janitor::make_clean_names(species),".png' />")) %>%
reactable(
columns = list(
plot = colDef(html = TRUE,
resizable = TRUE,
show=T)
))
Here is what I get:
Just as a check, doing this loads the graphic: magick::image_read("plots/adelie.png") so I am not sure what I am missing.

How could you supply multiple series to a line chart in R shiny using highcharter package and without hardcoding the series?

I'm trying to create a line chart using highcharts package with a time series dataframe that is similar to this one:
reprexDF <- data.frame(category = c("apples","oranges","bananas","limes"),
month1 = c(5,8,10,2),
month2 = c(NA,7,2,3),
month3 = c(NA, NA, 10,2),
month4 = c(11,12,5,9)
)
I want each row to be a separate line on the line chart that shows the trend for each category across months, all plotted on the same chart.
I tried parsing each row into a list with:
reprexDF <- highcharter::list_parse2(reprexDf)
and then attempting to plot with:
highchart() %>%
hc_plotOptions(line = list(marker = list(enabled = FALSE)))%>%
hc_add_series_list(reprexDF)
but I'm still not being able to plot this data.
I just really want to avoid having to hard code each series because the lists are supposed to be dynamic.
Would first convert your data frame to long. Then you can group_by category and use list_parse2 to make lists by category.
For this plot, I made sure month was numeric on x-axis. I renamed category to name so it would show up in legend and labels. And added connectNulls in case you wanted to connect points across missing values (NA).
library(highcharter)
library(tidyverse)
reprexDF2 <- reprexDF %>%
pivot_longer(cols = -category, names_to = "month", values_to = "value", names_pattern = "month(\\d)$") %>%
group_by(category) %>%
do(data = list_parse2(data.frame(as.numeric(.$month), .$value))) %>%
ungroup() %>%
rename(name = category)
highchart() %>%
hc_plotOptions(series = list(connectNulls = TRUE), line = list(marker = list(enabled = FALSE)))%>%
hc_add_series_list(reprexDF2)

R highcharter - grouped categories - missing label for group with one value only

R Code:
setwd(dirname(rstudioapi::getActiveDocumentContext()$path))
options(stringsAsFactors = FALSE)
rm(list = ls())
if (!require("pacman")) install.packages("pacman")
pacman::p_load("dplyr","tidyr","highcharter")
raw_data <- read.csv("results.csv")
DT <- data.table(raw_data)
cols <- c('Person','ABC_Capability','ABC_Sub.capability','Leadership.Facet','Facet.Score')
DT <- DT[, cols, with = FALSE]
names(DT) <- c('Person','Capability','Sub_Capability','SVL','Facet_Score')
DT <- dcast(DT, Capability + Sub_Capability + SVL ~ Person,
value.var = c('Facet_Score'))
DT1 <- DT %>%
group_by(name = Sub_Capability) %>%
do(categories = .$SVL) %>%
list_parse()
highchart() %>%
hc_chart(type = "bar") %>%
hc_title(text = "Some Title") %>%
hc_add_series(name="A", data = DT$Joan) %>%
hc_add_series(name="B", data = DT$Shane) %>%
hc_add_series(name="C", data = DT$Simon) %>%
hc_xAxis(categories = DT1)
Output:
I tried using a smaller dataset and realized every time there is a single value in a group. The label gets truncated. For example: Develops people > Empowering
Any help would be appreciated.
Like Kamil Kulig mentioned, you can try making the categories an array instead of vector and it worked for me. Using the sample code you provided, it would be:
DT1 <- DT %>%
group_by(name = Sub_Capability) %>%
# store SVL as array
do(categories = array(.$SVL)) %>%
list_parse()
New Update:
The vector needs to be converted to an array using the array() function even if you are not using grouped categories but simply wanted to rename the tick labels i.e.
highcharter::hchart(mtcars[1, ],
"column", name = "MPG",
highcharter::hcaes(x = 0, y = mpg),
showInLegend = F) %>%
# x axis format
highcharter::hc_xAxis(title = list(text ="Car Name"),
# relabel x axis tick to the name of the cars
categories = array(rownames(mtcars)[1]))
then the axis tick label will display the name of the car.
If you use simply categories = rownames(mtcars)[1]) instead of converting it into an array the x axis label won't display properly:
Here the tick label is just M instead of Mazada RX4.

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().

Resources