How to plot Highcharter side by side in RStudio Viewer? - r

I wanted to see an exact output of a Highcharter plot side by side in RStudio Viewer if it possible, exactly showed in this reference: http://jkunst.com/highcharter/highcharts.html, So let me define it like this for a simple usage
highcharter_all_plot <- function(){
library(highcharter)
library(dplyr)
library(stringr)
library(purrr)
n <- 5
set.seed(123)
colors <- c("#d35400", "#2980b9", "#2ecc71", "#f1c40f", "#2c3e50", "#7f8c8d")
colors2 <- c("#000004", "#3B0F70", "#8C2981", "#DE4968", "#FE9F6D", "#FCFDBF")
df <- data.frame(x = seq_len(n) - 1) %>%
mutate(
y = 10 + x + 10 * sin(x),
y = round(y, 1),
z = (x*y) - median(x*y),
e = 10 * abs(rnorm(length(x))) + 2,
e = round(e, 1),
low = y - e,
high = y + e,
value = y,
name = sample(fruit[str_length(fruit) <= 5], size = n),
color = rep(colors, length.out = n),
segmentColor = rep(colors2, length.out = n)
)
print(head(df))
create_hc <- function(t) {
dont_rm_high_and_low <- c("arearange", "areasplinerange",
"columnrange", "errorbar")
is_polar <- str_detect(t, "polar")
t <- str_replace(t, "polar", "")
if(!t %in% dont_rm_high_and_low){
df <- df %>% dplyr::select(-e, -low, -high)
}
highchart() %>%
hc_title(text = paste(ifelse(is_polar, "polar ", ""), t),
style = list(fontSize = "15px")) %>%
hc_chart(type = t,
polar = is_polar) %>%
hc_xAxis(categories = df$name) %>%
hc_add_series(df, name = "Fruit Consumption", showInLegend = FALSE)
}
hcs <- c("line", "spline", "area", "areaspline",
"column", "bar", "waterfall" , "funnel", "pyramid",
"pie" , "treemap", "scatter", "bubble",
"arearange", "areasplinerange", "columnrange", "errorbar",
"polygon", "polarline", "polarcolumn", "polarcolumnrange",
"coloredarea", "coloredline") %>% map(create_hc)
return(hcs)
}
x <- highcharter_all_plot()
#Then plot can be accessed in by calling x[[1]], x[[2]], x[[3]]..
As far as my understanding of side by side plot, I only know of 2 these handy methods, which is:
1) Using par(mfrow)
par(mfrow=c(3,4)) -> (which only can by applied to base plot)
2) Using grid.arrange from gridExtra
library(gridExtra)
grid.arrange(x[[1]], x[[2]], x[[3]], x[[4]], nrow=2, ncol=2)
-> (Cannot work since x not a ggplot type)
So I wanted to know if there is a way that this can be applied? I am new using Highcharter

If you inspect the Highcharter website you provided, you will see that those charts are not sided by side using R, but they are just renderer in separate HTML containers and positioned by bootstrap (CSS). So, if you want to render your charts in an HTML environment, I suggest rendering every chart into a separate div.
But maybe Shiny is a tool you are looking for. Maybe this is a duplicate of Shiny rcharts multiple chart output
Maybe this will help you too: https://github.com/jbkunst/highcharter/issues/37

Related

r plotly update button with line plot does not work with add_markers

I have a problem with the joined plot of an updatable line and static markers in R plotly. The line plot is updated via a drop down menu button, which works well on its own. The additional dots in the add_markers function are also correct when the plot is first initialized.
But after the first update, the markers are cut off (to the left side of the plot where the line starts) and remaining markers are modified (y values are different to initial ones).
For the example here the button function is simplified, but the result shows the same strange behavior.
`
sample_df <- tibble::tibble(quarter_date = rep(c("2022-06-30","2022-09-30","2022-12-31"),3),
forecast_value = runif(9,min = 10,max = 16),
forecast_date = c(rep("2022-07-23",3),rep("2022-08-26",3),rep("2022-09-15",3)))
marks = tibble::tibble(dates = c("2022-05-21","2022-06-15","2022-07-02","2022-07-26","2022-08-27"),
values = c(11,13,12,15,14))
create_buttons <- function(df, date_id) {
lapply(
date_id,
FUN = function(date_id,df) {
button <- list(
method = 'restyle',
args = list('y', list(df %>%
dplyr::filter(forecast_date == date_id) %>%
dplyr::pull(forecast_value))),
label = sprintf('Forecast # %s', date_id)
)
},
df
)
}
plotly::plot_ly(x = ~quarter_date) %>%
plotly::add_trace(data = sample_df %>%
dplyr::filter(forecast_date == max(forecast_date)),
#x = ~period_date,
y = ~forecast_value,
type = 'scatter',
mode = 'markers+lines',
name = 'forecasts') %>%
plotly::layout(
title = "Drop down menue",
yaxis = list(title = "y"),
updatemenus = list(
list(
y =1,
x = 0.9,
buttons = create_buttons(sample_df, unique(sample_df$forecast_date))
)
)) %>%
plotly::add_markers(data = marks,
x = ~dates,
y = ~values)
`
I have tried to set a wide xrange, used a second y2 axis and different approaches in the button calculation but nothing works as intended.
Does anyone have a clue why the add_markers is not working correctly after updating the line plot? Any ideas are highly appreciated!
Adding markers aren't the issue. The issue comes from the restyle. When you restyle the plot without designating that you only meant to change one trace, you changed all traces.
The solution is actually quite simple, you just need one more argument in your args call-- the trace number in a list: list(0) in this case. I've commented out your original args call, so you can see the change.
To make this repeatable, I added set.seed(46) before the creation of sample_df.
create_buttons <- function(df, date_id) {
lapply(
date_id,
FUN = function(date_id, df) {
button <- list(
method = 'restyle',
args = list('y', list(df %>% filter(forecast_date == date_id) %>%
pull(forecast_value)), list(0)),
# args = list('y', list(df %>%
# filter(forecast_date == date_id) %>%
# pull(forecast_value))),
label = sprintf('Forecast # %s', date_id)
)
},
df
)
}
Now when you run your plot, you will see that your marker data remains visible.

geom_label() equivalent in {echarts4r}

Issue
I'm trying to produce a visualisation using {echarts4r} that involves plotting points with labels displayed on the chart itself, where the labels are unrelated to the position of the points. This sounds like it should be simple, but so far I haven't found any viable method of doing this and I'm beginning to wonder if it's even possible.
Desired output
Here is a minimal example. I will use {ggplot2} to demonstrate what I'd (roughly) like to reproduce:
data <- data.frame(
date_eaten = as.Date(c("2020-01-01", "2020-01-02", "2020-01-03")),
tastiness = c(5, 7, 10),
fruit = c("apple", "orange", "mango")
)
data
#> date_eaten tastiness fruit
#> 1 2020-01-01 5 apple
#> 2 2020-01-02 7 orange
#> 3 2020-01-03 10 mango
library(ggplot2)
ggplot(data, aes(x = date_eaten, y = tastiness, label = fruit)) +
geom_point() +
geom_text(nudge_y = 0.2)
Attempt using e_labels()
This method is visually exactly what I want, however, it seems that there is no option to specify which columns to take the labels from.
library(echarts4r)
data %>%
e_chart(date_eaten) %>%
e_scatter(tastiness, symbol_size = 10) %>%
e_labels()
Attempt using e_mark_point()
This option allows for more customisation, however this is not really a viable solution as it is very clunky and doesn't strictly 'link back' to the original data:
data %>%
e_chart(date_eaten) %>%
e_scatter(tastiness, symbol_size = 10) %>%
e_mark_point(data = list(
xAxis = as.Date("2020-01-01"),
yAxis = 5,
value = "apple"
)) %>%
e_mark_point(data = list(
xAxis = as.Date("2020-01-02"),
yAxis = 7,
value = "orange"
)) %>%
e_mark_point(data = list(
xAxis = as.Date("2020-01-03"),
yAxis = 10,
value = "mango"
))
I think this is the solution. Currently I'm not sure exactly how it works as documentation is a bit limited, but it seems to work:
data %>%
e_chart(date_eaten) %>%
e_scatter(tastiness, symbol_size = 10, bind = fruit) %>%
e_labels(formatter = htmlwidgets::JS("
function(params) {
return(params.name)
}
"))

View venn.diagram in RStudio viewer (not just write to file) using VennDiagram?

Using the VennDiagram package, we can make a venn diagram like so with the venn.diagram() function like so:
library(tidyverse)
library(hrbrthemes)
library(tm)
library(proustr)
# Load dataset from github
data <- read.table("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/14_SeveralIndepLists.csv", header=TRUE)
to_remove <- c("_|[0-9]|\\.|function|^id|script|var|div|null|typeof|opts|if|^r$|undefined|false|loaded|true|settimeout|eval|else|artist")
data <- data %>% filter(!grepl(to_remove, word)) %>% filter(!word %in% stopwords('fr')) %>% filter(!word %in% proust_stopwords()$word)
# library
library(VennDiagram)
#Make the plot
venn.diagram(
x = list(
data %>% filter(artist=="booba") %>% select(word) %>% unlist() ,
data %>% filter(artist=="nekfeu") %>% select(word) %>% unlist() ,
data %>% filter(artist=="georges-brassens") %>% select(word) %>% unlist()
),
category.names = c("Booba (1995)" , "Nekfeu (663)" , "Brassens (471)"),
filename = 'venn.png',
output = TRUE ,
imagetype="png" ,
height = 480 ,
width = 480 ,
resolution = 300,
compression = "lzw",
lwd = 1,
col=c("#440154ff", '#21908dff', '#fde725ff'),
fill = c(alpha("#440154ff",0.3), alpha('#21908dff',0.3), alpha('#fde725ff',0.3)),
cex = 0.5,
fontfamily = "sans",
cat.cex = 0.3,
cat.default.pos = "outer",
cat.pos = c(-27, 27, 135),
cat.dist = c(0.055, 0.055, 0.085),
cat.fontfamily = "sans",
cat.col = c("#440154ff", '#21908dff', '#fde725ff'),
rotation = 1
)
This results in a .png written to the working directly.
How can it instead be viewed in the RStudio viewer pane, and also used in RMarkdown docs etc (i.e. just in the same way a regular ggplot or base plots would be viewed)?
Also note, the same question applies to any of the examples found in the ?
venn.diagram documentation (they all seem to write to file instead of display in the RStudio viewer)
This should also do the job. I deleted the arguments for readability:
...
plt <- venn.diagram(
filename = NULL,
cex = 1,
cat.cex = 1,
lwd = 2,
)
grid::grid.draw(plt)
From ?venn.diagram
filename
Filename for image output, or if NULL returns the grid object itself
It seems, you can control almost anything. Again the docs:
... A series of graphical parameters tweaking the plot. See below for
details Details
Argument Venn Sizes Class Description
cex 1,2,3,4,5 numeric Vector giving the size for each area label (length = 1/3/7/15 based on set-number)
Thus we need to be able to display grid objects. plot() and print() don't do this job (it seems there is not print.grid()).
I usually do:
library(VennDiagram)
set.seed(1)
list1 <- list(A=sample(LETTERS, 12), B=sample(LETTERS, 12))
venn1 <- venn.diagram(list1, filename = NULL)
grid.newpage()
grid.draw(venn1)
I think it still writes a log file into the working directory, but not the graph.
You can put two diagrams side by side like this:
library(gridExtra)
set.seed(2)
list2 <- list(A=sample(LETTERS, 16), B=sample(LETTERS, 12))
venn2 <- venn.diagram(list2, filename = NULL)
grid.arrange(gTree(children=venn1),
gTree(children=venn2),
ncol=2)
Created on 2020-04-23 by the reprex package (v0.3.0)
I figured out a way - there may be better way(s). This involves writing to tempfile() instead of a file in the working directory and then reading it in with a few extra lines of code
Note: the only changes to the original code are the addition of
1 extra line at the start temp_file <- tempfile()
the rewriting of filename = 'venn.png' into filename = temp_file
3 extra lines at the bottom
# Libraries
library(tidyverse)
library(hrbrthemes)
library(tm)
library(proustr)
# Load dataset from github
data <- read.table("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/14_SeveralIndepLists.csv", header=TRUE)
to_remove <- c("_|[0-9]|\\.|function|^id|script|var|div|null|typeof|opts|if|^r$|undefined|false|loaded|true|settimeout|eval|else|artist")
data <- data %>% filter(!grepl(to_remove, word)) %>% filter(!word %in% stopwords('fr')) %>% filter(!word %in% proust_stopwords()$word)
# library
library(VennDiagram)
temp_file <- tempfile()
#Make the plot
venn.diagram(
x = list(
data %>% filter(artist=="booba") %>% select(word) %>% unlist() ,
data %>% filter(artist=="nekfeu") %>% select(word) %>% unlist() ,
data %>% filter(artist=="georges-brassens") %>% select(word) %>% unlist()
),
category.names = c("Booba (1995)" , "Nekfeu (663)" , "Brassens (471)"),
filename = temp_file,
output = TRUE ,
imagetype="png" ,
height = 480 ,
width = 480 ,
resolution = 300,
compression = "lzw",
lwd = 1,
col=c("#440154ff", '#21908dff', '#fde725ff'),
fill = c(alpha("#440154ff",0.3), alpha('#21908dff',0.3), alpha('#fde725ff',0.3)),
cex = 0.5,
fontfamily = "sans",
cat.cex = 0.3,
cat.default.pos = "outer",
cat.pos = c(-27, 27, 135),
cat.dist = c(0.055, 0.055, 0.085),
cat.fontfamily = "sans",
cat.col = c("#440154ff", '#21908dff', '#fde725ff'),
rotation = 1
)
# https://stackoverflow.com/a/20909108/5783745
library(png)
img <- readPNG(temp_file)
grid::grid.raster(img)

Error "not numeric" when using crosstalk package with EnhancedVolcano

I'd like to implement a cross-talk functionality between a table and plot in both directions:
select the row in the table which will be reflected in the plot
select a dot in the plot which will be reflected in the table. Same idea as here.
I've managed to implement a script, which works beautifully if I make scatter plot with ggplot() and table (both objects cross-talk!). However, when used EnhancedVolcano() and table I got the following error:
Error in EnhancedVolcano(toptable = data_shared, lab = "disp", x = "qsec", :
qsec is not numeric!
If I replace data_shared variable with df_orig, no error is raised, but there is no cross-talking between objects :(
Does this mean that SharedData$new() doesn't recognize numeric values as numeric? How to fix this error?
Any help is highly appreciated.
Thank you
Toy example:
library(plotly) # '4.9.1'
library(DT) # '0.11'
library(crosstalk) # ‘1.0.0’
library(EnhancedVolcano) # ‘1.4.0’
# Input
data1 = mtcars #dim(data1) # 32 11
data_shared = SharedData$new(data1) #, key = c("qsec", "hp"))
# df_orig = data_shared$origData()
# V-Plot
vp =EnhancedVolcano( toptable = data_shared,
lab = 'disp',
x = 'qsec',
y = 'hp',
xlab ='testX',
ylab = 'testY')
bscols(
ggplotly(vp + aes(x= qsec, y= -log10(hp/1000))),
datatable(data_shared, style="bootstrap", class="compact", width="100%",
options=list(deferRender=FALSE, dom='t')))
Same script, which works with ggplot():
data1 = mtcars #dim(data1) # 32 11
data_shared = SharedData$new(data1)
vp = ggplot(data = data_shared, mapping = aes(qsec, hp)) +
geom_point()
bscols(
ggplotly(vp) ,
datatable(data_shared, style="bootstrap", class="compact", width="100%",
options=list(deferRender=FALSE, dom='t')))
Note: Related (same) question was posted at BioStars, and the package author posted an answer, with author's permission copying an answer here:
Hi,
Thanks - that's very useful code and I may add it to the main package vignette, eventually.
I tried it here on my computer and I was able to get it working in my browser, but some components of the original plot seem to have been lost. I think that you just need to convert your column, 'qsec', to numerical values.
Re-using an example from my Vignette, here is a perfectly reproducible example:
library("pasilla")
pasCts <- system.file("extdata", "pasilla_gene_counts.tsv",
package="pasilla", mustWork=TRUE)
pasAnno <- system.file("extdata", "pasilla_sample_annotation.csv",
package="pasilla", mustWork=TRUE)
cts <- as.matrix(read.csv(pasCts,sep="\t",row.names="gene_id"))
coldata <- read.csv(pasAnno, row.names=1)
coldata <- coldata[,c("condition","type")]
rownames(coldata) <- sub("fb", "", rownames(coldata))
cts <- cts[, rownames(coldata)]
library("DESeq2")
dds <- DESeqDataSetFromMatrix(countData = cts,
colData = coldata,
design = ~ condition)
featureData <- data.frame(gene=rownames(cts))
mcols(dds) <- DataFrame(mcols(dds), featureData)
dds <- DESeq(dds)
res <- results(dds)
library(EnhancedVolcano)
p1 <- EnhancedVolcano(res,
lab = rownames(res),
x = "log2FoldChange",
y = "pvalue",
pCutoff = 10e-4,
FCcutoff = 2,
xlim = c(-5.5, 5.5),
ylim = c(0, -log10(10e-12)),
pointSize = c(ifelse(res$log2FoldChange>2, 8, 1)),
labSize = 4.0,
shape = c(6, 6, 19, 16),
title = "DESeq2 results",
subtitle = "Differential expression",
caption = "FC cutoff, 1.333; p-value cutoff, 10e-4",
legendPosition = "right",
legendLabSize = 14,
col = c("grey30", "forestgreen", "royalblue", "red2"),
colAlpha = 0.9,
drawConnectors = TRUE,
hline = c(10e-8),
widthConnectors = 0.5)
p1 <- p1 +
ggplot2::coord_cartesian(xlim=c(-6, 6)) +
ggplot2::scale_x_continuous(
breaks=seq(-6,6, 1))
library(plotly)
library(DT)
library(crosstalk)
bscols(
ggplotly(p1 + aes(x= log2FoldChange, y= -log10(pvalue))),
datatable(
data.frame(res),
style="bootstrap",
class="compact", width="100%",
options=list(deferRender=FALSE, dom='t')))
Unfortunately, plotly and/or bscols don't like the use of bquote(), so, one cannot have the fancy axes names that I use in EnhancedVolcano:
... + xlab(bquote(~Log[2] ~ "fold change")) + ylab(bquote(~-Log[10] ~ italic(P)))
When i try to add these, it throws an error.
Kevin
tried to modify few things in volcano function, got following error:
Error in as.data.frame.default(toptable) :
cannot coerce class ‘c("SharedData", "R6")’ to a data.frame
not sure yet, how to fix it.

Customize colors for boxplot with highcharter

I have boxplots on highcharter and I would like to customize both the
Fill color
Border color
Here is my code
df = data.frame(cbind(categ = rep(c('a','b','c','d')),value = rnorm(1000)))
hcboxplot(var = df$categ, x = as.numeric(df$value)) %>%
hc_chart(type = "column") %>%
hc_colors(c("#203d7d","#a0a0ed","#203d7e","#a0a0ad"))
The hc_colors works only if I put var2 instead of var but then the box plot are shrunken...
API for styling fillColor: https://api.highcharts.com/highcharts/series.boxplot.fillColor
And for "Border color": https://api.highcharts.com/highcharts/series.boxplot.color
Pure JavaScript example of how to style and define points: https://jsfiddle.net/BlackLabel/6tud3fgx
And R code:
library(highcharter)
df = data.frame(cbind(categ = rep(c('a','b','c','d', 'e')),value = rnorm(1000)))
hcboxplot(var = df$categ, x = as.numeric(df$value)) %>%
hc_chart(type = "column", events = list(
load = JS("function() {
var chart = this;
chart.series[0].points[2].update({
color: 'red'
})
chart.series[0].points[4].update({
x: 4,
low: 600,
q1: 700,
median: 800,
q3: 900,
high: 1000,
color: 'orange'
})
}")
)) %>%
hc_plotOptions(boxplot = list(
fillColor = '#F0F0E0',
lineWidth = 2,
medianColor = '#0C5DA5',
medianWidth = 3,
stemColor = '#A63400',
stemDashStyle = 'dot',
stemWidth = 1,
whiskerColor = '#3D9200',
whiskerLength = '20%',
whiskerWidth = 3,
color = 'black'
)) %>%
hc_colors(c("#203d7d","#a0a0ed","#203d7e","#a0a0ad"))
I made a couple functions to do some stuff with highcharts and boxplots. It will let you color each boxplot and fill it accordingly, and then inject new graphical parameters according to the Highcharts API, should you desire.
Check it out:
## Boxplots Data and names, note the data index (0,1,2) is the first number in the datum
series<- list(
list(
name="a",
data=list(c(0,1,2,3,4,5))
),
list(
name="b",
data=list(c(1,2,3,4,5,6))
),
list(
name="c",
data=list(c(2,3,4,5,6,7))
)
)
# Graphical attribute to be set: fillColor.
# Make the colors for the box fill and then also the box lines (make them match so it looks pretty)
cols<- viridisLite::viridis(n= length(series2), alpha = 0.5) # Keeping alpha in here! (for box fill)
cols2<- substr(cols, 0,7) # no alpha, pure hex truth, for box lines
gen_key_vector<-function(variable, num_times){
return(rep(variable, num_times))
}
kv<- gen_key_vector(variable = "fillColor", length(series))
# Make a function to put stuff in the 'series' list, requires seq_along to be used since x is the list/vector index tracker
add_variable_to_series_list<- function(x, series_list, key_vector, value_vector){
base::stopifnot(length(key_vector) == length(value_vector))
base::stopifnot(length(series_list) == length(key_vector))
series_list[[x]][length(series_list[[x]])+1]<- value_vector[x]
names(series_list[[x]])[length(series_list[[x]])]<- key_vector[x]
return(series_list[[x]])
}
## Put the extra stuff in the 'series' list
series2<- lapply(seq_along(series), function(x){ add_variable_to_series_list(x = x, series_list = series, key_vector = kv, value_vector = cols) })
hc<- highcharter::highchart() %>%
highcharter::hc_chart(type="boxplot", inverted=FALSE) %>%
highcharter::hc_title(text="This is a title") %>%
highcharter::hc_legend(enabled=FALSE) %>%
highcharter::hc_xAxis(type="category", categories=c("a", "b", "c"), title=list(text="Some x-axis title")) %>%
highcharter::hc_add_series_list(series2) %>%
hc_plotOptions(series = list(
marker = list(
symbol = "circle"
),
grouping=FALSE
)) %>%
highcharter::hc_colors(cols2) %>%
highcharter::hc_exporting(enabled=TRUE)
hc
This probably could be adjusted to work with a simple dataframe, but I think it will get you what you want for right now without having to do too much extra work. Also, maybe look into list_parse or list_parse2' fromhighcharter...it could probably help with building out theseries` object..I still need to look into that.
Edit:
I have expanded the example to make it work with a regular DF. As per some follow up questions, the colors are set using the viridis palette inside the make_highchart_boxplot_with_colored_factors function. If you want to allow your own palette and colors, you could expose those arguments and just include them as parameters inside the function call. The expanded example borrows how to add outliers from the highcharter library (albeit in a hacky way) and then builds everything else up from scratch. Hopefully this helps clarify my previous answer. Please note, I could probably also clean up the if condition to make it a little more brief, but I kept it verbose for illustrative purposes.
Double Edit: You can now specify a vector of colors for each level of the factor variable
library(highcharter)
library(magrittr)
library(viridisLite)
df = data.frame(cbind(categ = rep(c('a','b','c','d')),value = rnorm(1000)))
df$value<- base::as.numeric(df$value)
add_variable_to_series_list<- function(x, series_list, key_vector, value_vector){
base::stopifnot(length(key_vector) == length(value_vector))
base::stopifnot(length(series_list) == length(key_vector))
series_list[[x]][length(series_list[[x]])+1]<- value_vector[x]
names(series_list[[x]])[length(series_list[[x]])]<- key_vector[x]
return(series_list[[x]])
}
# From highcharter github pages:
hc_add_series_bwpout = function(hc, value, by, ...) {
z = lapply(levels(by), function(x) {
bpstats = boxplot.stats(value[by == x])$stats
outliers = c()
for (y in na.exclude(value[by == x])) {
if ((y < bpstats[1]) | (y > bpstats[5]))
outliers = c(outliers, list(which(levels(by)==x)-1, y))
}
outliers
})
hc %>%
hc_add_series(data = z, type="scatter", ...)
}
gen_key_vector<-function(variable, num_times){
return(rep(variable, num_times))
}
gen_boxplot_series_from_df<- function(value, by,...){
value<- base::as.numeric(value)
by<- base::as.factor(by)
box_names<- levels(by)
z=lapply(box_names, function(x) {
boxplot.stats(value[by==x])$stats
})
tmp<- lapply(seq_along(z), function(x){
var_name_list<- list(box_names[x])
#tmp0<- list(names(df)[x])
names(var_name_list)<- "name"
index<- x-1
tmp<- list(c(index, z[[x]]))
tmp<- list(tmp)
names(tmp)<- "data"
tmp_out<- c(var_name_list, tmp)
#tmp<- list(tmp)
return(tmp_out)
})
return(tmp)
}
# Usage:
#series<- gen_boxplot_series_from_df(value = df$total_value, by=df$asset_class)
## Boxplot function:
make_highchart_boxplot_with_colored_factors<- function(value, by, chart_title="Boxplots",
chart_x_axis_label="Values", show_outliers=FALSE,
boxcolors=NULL, box_line_colors=NULL){
by<- as.factor(by)
box_names_to_use<- levels(by)
series<- gen_boxplot_series_from_df(value = value, by=by)
if(is.null(boxcolors)){
cols<- viridisLite::viridis(n= length(series), alpha = 0.5) # Keeping alpha in here! (COLORS FOR BOXES ARE SET HERE)
} else {
cols<- boxcolors
}
if(is.null(box_line_colors)){
if(base::nchar(cols[[1]])==9){
cols2<- substr(cols, 0,7) # no alpha, pure hex truth, for box lines
} else {
cols2<- cols
}
} else {
cols2<- box_line_colors
}
# Injecting value 'fillColor' into series list
kv<- gen_key_vector(variable = "fillColor", length(series))
series2<- lapply(seq_along(series), function(x){ add_variable_to_series_list(x = x, series_list = series, key_vector = kv, value_vector = cols) })
if(show_outliers == TRUE){
hc<- highcharter::highchart() %>%
highcharter::hc_chart(type="boxplot", inverted=FALSE) %>%
highcharter::hc_title(text=chart_title) %>%
highcharter::hc_legend(enabled=FALSE) %>%
highcharter::hc_xAxis(type="category", categories=box_names_to_use, title=list(text=chart_x_axis_label)) %>%
highcharter::hc_add_series_list(series2) %>%
hc_add_series_bwpout(value = value, by=by, name="Outliers") %>%
hc_plotOptions(series = list(
marker = list(
symbol = "circle"
),
grouping=FALSE
)) %>%
highcharter::hc_colors(cols2) %>%
highcharter::hc_exporting(enabled=TRUE)
} else{
hc<- highcharter::highchart() %>%
highcharter::hc_chart(type="boxplot", inverted=FALSE) %>%
highcharter::hc_title(text=chart_title) %>%
highcharter::hc_legend(enabled=FALSE) %>%
highcharter::hc_xAxis(type="category", categories=box_names_to_use, title=list(text=chart_x_axis_label)) %>%
highcharter::hc_add_series_list(series2) %>%
hc_plotOptions(series = list(
marker = list(
symbol = "circle"
),
grouping=FALSE
)) %>%
highcharter::hc_colors(cols2) %>%
highcharter::hc_exporting(enabled=TRUE)
}
hc
}
# Usage:
tst_box<- make_highchart_boxplot_with_colored_factors(value = df$value, by=df$categ, chart_title = "Some Title", chart_x_axis_label = "Some X Axis", show_outliers = TRUE)
tst_box
# Custom Colors:
custom_colors_with_alpha_in_hex<- paste0(gplots::col2hex(sample(x=colors(), size = length(unique(df$categ)), replace = FALSE)), "80")
tst_box2<- make_highchart_boxplot_with_colored_factors(value = df$value, by=df$categ, chart_title = "Some Title",
chart_x_axis_label = "Some X Axis",
show_outliers = TRUE, boxcolors = custom_colors_with_alpha_in_hex)
tst_box2
tst_box3<- make_highchart_boxplot_with_colored_factors(value = df$value, by=df$categ, chart_title = "Some Title",
chart_x_axis_label = "Some X Axis",
show_outliers = TRUE, boxcolors = custom_colors_with_alpha_in_hex, box_line_colors = "black")
tst_box3
I hope this helps, please let me know if you have any more questions. I'm happy to try to help as best I can.
-nate
Since there's no highcharter answer yet, I give you at least a base solution.
First, your definition of the data frame is somewhat flawed, rather do:
dat <- data.frame(categ=c('a','b','c','d'), value=rnorm(1000))
Now, using boxplot is quite straightforward. border option colors your borders. With option col you also could color the fills.
boxplot(value ~ categ, dat, border=c("#203d7d","#a0a0ed","#203d7e","#a0a0ad"), pars=list(outpch=16))
Gives
Note: See this nice solution for further customizations.

Resources