使用HighCharter自定义箱形图的颜色

时间:2019-03-13 03:52:12

标签: r highcharts colors boxplot r-highcharter

我在highcharter上有框图,我想同时定制

  • 填充颜色
  • 边框颜色

这是我的代码

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")) 

仅当我放置var2而不是var时,hc_colors才起作用,但是方框图变小了……

3 个答案:

答案 0 :(得分:1)

用于设置 fillColor 的API:https://api.highcharts.com/highcharts/series.boxplot.fillColor

对于“边框颜色” https://api.highcharts.com/highcharts/series.boxplot.color

有关如何设置样式和定义点的纯JavaScript示例:https://jsfiddle.net/BlackLabel/6tud3fgx

和R代码:

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"))

答案 1 :(得分:0)

由于还没有highcharter的答案,因此我至少给您一个基本的解决方案。

首先,您对数据框的定义有些瑕疵,请这样做:

dat <- data.frame(categ=c('a','b','c','d'), value=rnorm(1000))

现在,使用boxplot非常简单。 border选项为边框加色。使用选项col,您还可以为填充填充颜色。

boxplot(value ~ categ, dat, border=c("#203d7d","#a0a0ed","#203d7e","#a0a0ad"), pars=list(outpch=16))

给予

enter image description here

注意: :有关进一步的自定义,请参见this nice solution

答案 2 :(得分:0)

我做了几个功能,可以用高图和箱图做一些事情。它将使您为每个箱线图着色并相应地填充它,然后根据需要根据Highcharts API注入新的图形参数。

签出:

## 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

可以将其调整为与简单的数据框一起使用,但是我认为它可以立即满足您的需求,而无需执行过多的额外工作。另外,也许要研究list_parselist_parse2' from highcharter ...it could probably help with building out the系列的对象。我仍然需要研究这个对象。

编辑:

我已经扩展了示例,使其可以与常规DF一起使用。根据一些后续问题,使用viridis函数内的make_highchart_boxplot_with_colored_factors调色板设置颜色。如果要允许自己的调色板和颜色,则可以公开这些参数,并将其作为参数包含在函数调用中。扩展后的示例借鉴了如何从highcharter库中添加离群值(尽管采用了怪异的方式),然后从头开始构建其他所有内容。希望这有助于澄清我以前的答案。请注意,我可能还可以清理if条件,使其更为简短,但出于说明目的,我将其保持冗长。

双重编辑:您现在可以为每个因子变量级别指定颜色矢量

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

我希望这会有所帮助,如果您还有其他疑问,请告诉我。我很乐意尽我所能。 -nate