基于Highcharts的双序列差异化百分比变动展示优化问询
优化Highcharts Tooltip差异化百分比计算的实现方案
问题背景
拥有两个带DATE列的数据集:data(AUM序列)和data2(Cumulative NP序列),需在不改变Y轴单位的前提下实现两种差异化百分比计算:
- AUM序列:计算当前值相对视图内首个值的百分比变动,公式为
(y - compVal)/compVal * 100(compVal为视图内AUM的首个值) - Cumulative NP序列:计算当前值与视图内AUM首个值的占比,公式为
y/compVal * 100(compVal同样为视图内AUM的首个值)
现有实现中,tooltip的pref2函数通过全局变量传递compVal,代码耦合性高,需优化实现方式。
优化思路
直接在tooltip formatter中获取基准值并整合计算逻辑,避免全局变量依赖:
- 通过Highcharts的
chart.get('aum_line')直接定位AUM主序列,获取其视图内首个值dataModify.compareValue作为统一基准compVal - 遍历tooltip点,根据序列名称自动匹配对应的百分比计算逻辑,合并重复代码,提升可维护性
完整优化代码
data <- structure(list(DATE = structure(c(19327, 19328, 19331, 19332, 19333, 19334, 19335, 19338, 19339, 19340, 19341, 19342, 19345, 19346, 19347, 19348, 19349), class = "Date"), AUM = c(32962594L, 33213220L, 33278745L, 33482196L, 33591402L, 33591402L, 33660796L, 33810382L, 34172853L, 34264748L, 34032274L, 34216610L, 34416588L, 34462226L, 35308681L, 35429483L, 35456650L)), row.names = c(NA, -17L), class = "data.frame") data2 <- structure(list(DATE = structure(c(19327, 19328, 19331, 19332, 19333, 19334, 19335, 19338, 19339, 19340, 19341, 19342, 19345, 19346, 19347, 19348, 19349), class = "Date"), CUM_SUM = c(0L, 173080L, 318158L, 504538L, 607304L, 607304L, 771404L, 916984L, 1153354L, 1292314L, 1381434L, 1708534L, 1937284L, 2035272L, 2817863L, 3046949L, 3046949L)), row.names = c(NA, -17L), class = "data.frame") # Line Plot: highchart() %>% hc_title(text = list('Combined')) %>% hc_add_series(name = "AUM", yAxis = 0, id = "aum_line", data = data, type = 'line', hcaes(x = DATE, y = AUM), events = list( legendItemClick = htmlwidgets::JS( "function(e) { var shown = this.visible ? false : true; this.update({visible: shown}); return false; }" ))) %>% hc_add_series(name = "AUM",id = 'aum_line_percent', data = data, type = "line", hcaes(x = DATE, y = AUM), compare = 'percent', linkedTo = 'aum_line', visible = F) %>% hc_add_series(name = 'Cumulative NP', yAxis = 1, id = 'pl_cum_line', data = data2, type = 'line', hcaes(x = DATE, y = CUM_SUM), events = list( legendItemClick = htmlwidgets::JS( "function(e) { var shown = this.visible ? false : true; this.update({visible: shown}); return false; }" ))) %>% hc_add_series(name = "Cumulative NP",id = 'pl_cum_line_percent', data = data2, type = "line", hcaes(x = DATE, y = CUM_SUM), compare = 'percent', linkedTo = 'pl_cum_line', visible = F) %>% hc_yAxis_multiples(list(title = list(text = "AUM", style = list(fontSize = "1.5em", color = '#607B8B' )), opposite = FALSE), list(showLastLabel = FALSE, opposite = TRUE, title = list(text = "Cumulative NP", style = list(fontSize = "1.5em", color = '#CD8162')))) %>% hc_xAxis(type = "datetime") %>% hc_plotOptions(column = list(dataLabels = list(enabled = F),enableMouseTracking = T)) %>% hc_chart(zoomType = 'xy') %>% hc_colors(c('#607B8B','#607B8B','#CD8162','#CD8162')) %>% hc_tooltip(split = T, crosshairs = T, formatter = htmlwidgets::JS( "function() { // 获取视图内AUM序列的首个基准值 const compVal = this.chart.get('aum_line').dataModify.compareValue; const xform = Highcharts.dateFormat('%B %e, %Y', this.x); const tooltipLines = [xform]; this.points.forEach(pts => { const col = pts.color; let y = pts.y; const nm = pts.series.name; let delta; // 根据序列名称匹配计算逻辑 if (nm === 'AUM') { delta = (y - compVal) / compVal * 100; } else { delta = y / compVal * 100; } const adder = `(${delta.toFixed(2)}%)`; y = Highcharts.numberFormat(y, 0, '.', ' '); tooltipLines.push(`<b><span style='color:${col};'>● ${nm}:</span></b> ${y} ${adder}`); }); return tooltipLines; }" )) %>% hc_chart(events = list(load = JS("function() { var chart = this; chart.update({ chart: { backgroundColor: '#FFFFFF' } }); }"))) %>% hc_exporting(enabled = TRUE)
效果验证
- AUM序列:
(33213220-32962594)/32962594 * 100% = 0.76%,计算逻辑正确 - Cumulative NP序列:
173080/32962594 * 100% = 0.53%,计算逻辑正确
内容的提问来源于stack exchange,提问作者Caetano Almeida e Brito
相关产品推荐
相关产品推荐

