Highcharts: Stacked bar chart display categories data, not series - highcharts

I have two JS associative arrays that look like this:
var distroDates = [
{
name: 'exDate',
data: [
'06/25/2013',
'12/17/2012',
'06/20/2012',
'12/19/2011',
'06/21/2011',
'12/20/2010',
'06/21/2010',
'12/21/2009',
'06/22/2009',
'12/22/2008',
'06/23/2008',
'12/24/2007',
'12/21/2006',
'12/23/2005',
'12/23/2004',
'12/22/2003',
'12/23/2002'
]
},
{
name: 'Record Date',
data: [
'06/27/2013',
'12/19/2012',
'06/22/2012',
'12/21/2011',
'06/23/2011',
'12/22/2010',
'06/23/2010',
'12/23/2009',
'06/24/2009',
'12/24/2008',
'06/25/2008',
'12/27/2007',
'12/26/2006',
'12/28/2005',
'12/28/2004',
'12/24/2003',
'12/26/2002'
]
},
{
name: 'Payable Date',
data: [
'07/02/2013',
'12/24/2012',
'06/27/2012',
'12/29/2011',
'06/27/2011',
'12/30/2010',
'06/25/2010',
'12/31/2009',
'06/26/2009',
'12/31/2008',
'06/27/2008',
'01/04/2008',
'12/28/2006',
'12/30/2005',
'12/30/2004',
'01/02/2004',
'01/02/2003'
]
}
]
var distroData = [
{
name: 'Income',
data: [
0.3908,
0.4948,
0.2311,
0.3342,
0.245,
0.2213,
0.19,
0.1404,
0.2014,
0.2266,
0.2131,
0.2328,
0.1288,
0.0044,
0.6248,
0,
0
]
},
{
name: 'S.T. Capital Gains',
data: [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
]
},
{
name: 'L.T. Capital Gains',
data: [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
]
},
{
name: 'Return on Capital',
data: [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0.0202,
0,
0,
0
]
}
]
The distroData array is used for the series. The distroDates is used for the categories. I want the categories to display in the tooltip (rather than the usual series data) and I want the tooltip to update with the category values as I hover over each bar along the x-axis.
The following code accomplished this using Highcharts v2.1.4/Highstock v1.2.5 (both are loaded):
tooltip: {
formatter: function() {
var s = '<table class="tooltip distro"><tbody>';
var chart = this.points[0].series.chart; //get the chart object
var categories = chart.xAxis[0].categories; //get the categories array
var index = 0;
var distroDataPoint;
while(this.x !== categories[index]){index++;} //compute the index of corr y value in each data arrays
$.each(distroDates, function(i, categories) { //loop through categories array
s += '<tr><td>'+ categories.name +':</td><td>' + categories.data[index] + '</td></tr>'; //use index to peg categories and distro data to series
distroDataPoint = '<tr><td>Distribution:</td><td>$' + distroData[0].data[index] + '</td></tr>';
});
s += distroDataPoint + '</tbody></table>'
return s;
},
shared: true
},
However, when I upgraded to Highstock 1.3.4 (which includes Highcharts) the while statement locked my browser (FF and Chrome). The browser gave the familiar "Script is non-responsive" alert I assume because it was caught in an expensive loop.
Any ideas how I can rewrite or substitute the while so that performance is acceptable?

Why don't you just use shared tooltip? Just set tooltip.shared = true and everything will work fine. See example how to format shared tooltip here.

Related

Extract all percentages present within a text imported by IMPORTXML (Google Sheets)

As these percentages are within a function that creates the bar chart, the only way I was able to extract this data was by importing the entire function with this formula:
=IMPORTXML(
"https://int.soccerway.com/teams/spain/real-madrid-club-de-futbol/2016/statistics/",
"//div[#id='charts']//script[#type='text/javascript']")
The result is the following value:
(function(){ function drawScoringMinutesChart() { var hSize = 180, vSize =
180; var opts = { width: hSize, height: vSize, axisTitlesPosition: 'none',
legend: 'none', chartArea: { left: 0, top: 0, width: hSize, height: vSize
}, backgroundColor: '#f4f4f4', colors: ['#f85f00'], hAxis: { textPosition:
'none', viewWindowMode: 'explicit', viewWindow: { min: 0, max: 8 },
baselineColor: '#999999' }, vAxis: { textPosition: 'in' },
enableInteractivity: true }; var data_a = new
google.visualization.DataTable(); data_a.addColumn('string', 'Minute');
data_a.addColumn('number', 'Goals'); data_a.addRows(6); data_a.setValue(0,
0, '20.0%'); data_a.setValue(0, 1, 6); data_a.setValue(1, 0, '13.3%');
data_a.setValue(1, 1, 4); data_a.setValue(2, 0, '3.3%'); data_a.setValue(2,
1, 1); data_a.setValue(3, 0, '23.3%'); data_a.setValue(3, 1, 7);
data_a.setValue(4, 0, '13.3%'); data_a.setValue(4, 1, 4);
data_a.setValue(5, 0, '26.7%'); data_a.setValue(5, 1, 8); var chart_a = new
google.visualization.BarChart(document.getElementById('scoring_minutes_chart_a'));
chart_a.draw(data_a, opts); } $scru.execute(drawScoringMinutesChart,
['google:visualization']); })();
I would like to know if there is any formula that would be able to filter this text and deliver only the percentages, like this:
20.0%
13.3%
3.3%
23.3%
13.3%
26.7%
So that I can, in the end, put it like this in the spreadsheet:
0-15' 20.0%
15-30' 13.3%
30-45' 3.3%
45-60' 23.3%
60-75' 13.3%
75-90' 26.7%
try:
=QUERY(FLATTEN(SPLIT(REGEXREPLACE(IMPORTXML(A1,
"//div[#id='charts']//script[#type='text/javascript']"),
"[^(\d+.\d+%)]", " "), " ")),
"where Col1 contains '%'", 0)

How to calculate cpu utilization of container in docker using http api

I know that the CPU utilization of the container can be obtained by docker stats:
#docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
05076af468cd mystifying_kepler 0.02% 10.5MiB / 5.712GiB 0.18% 656B / 0B 0B / 0B 1
And I want to get this data through the HTTP api:http api.
Data i get from this http api is :
{
"read": "2019-11-26T22:18:33.027963669Z",
"preread": "2019-11-26T22:18:32.013978454Z",
"pids_stats": {
"current": 1
},
"blkio_stats": {
"io_service_bytes_recursive": [],
"io_serviced_recursive": [],
"io_queue_recursive": [],
"io_service_time_recursive": [],
"io_wait_time_recursive": [],
"io_merged_recursive": [],
"io_time_recursive": [],
"sectors_recursive": []
},
"num_procs": 0,
"storage_stats": {},
"cpu_stats": {
"cpu_usage": {
"total_usage": 361652820,
"percpu_usage": [361652820],
"usage_in_kernelmode": 50000000,
"usage_in_usermode": 100000000
},
"system_cpu_usage": 144599100000000,
"online_cpus": 1,
"throttling_data": {
"periods": 0,
"throttled_periods": 0,
"throttled_time": 0
}
},
"precpu_stats": {
"cpu_usage": {
"total_usage": 361488978,
"percpu_usage": [361488978],
"usage_in_kernelmode": 50000000,
"usage_in_usermode": 100000000
},
"system_cpu_usage": 144598090000000,
"online_cpus": 1,
"throttling_data": {
"periods": 0,
"throttled_periods": 0,
"throttled_time": 0
}
},
"memory_stats": {
"usage": 11005952,
"max_usage": 11108352,
"stats": {
"active_anon": 11005952,
"active_file": 0,
"cache": 0,
"dirty": 0,
"hierarchical_memory_limit": 9223372036854771712,
"hierarchical_memsw_limit": 9223372036854771712,
"inactive_anon": 0,
"inactive_file": 0,
"mapped_file": 0,
"pgfault": 8151,
"pgmajfault": 0,
"pgpgin": 4137,
"pgpgout": 1450,
"rss": 11005952,
"rss_huge": 0,
"total_active_anon": 11005952,
"total_active_file": 0,
"total_cache": 0,
"total_dirty": 0,
"total_inactive_anon": 0,
"total_inactive_file": 0,
"total_mapped_file": 0,
"total_pgfault": 8151,
"total_pgmajfault": 0,
"total_pgpgin": 4137,
"total_pgpgout": 1450,
"total_rss": 11005952,
"total_rss_huge": 0,
"total_unevictable": 0,
"total_writeback": 0,
"unevictable": 0,
"writeback": 0
},
"limit": 6133108736
},
"name": "/mystifying_kepler",
"id": "05076af468cdeb3d15d147a25e8ccee5f4d029ffcba1d60f14f84e2c9e25d6a9",
"networks": {
"eth0": {
"rx_bytes": 656,
"rx_packets": 8,
"rx_errors": 0,
"rx_dropped": 0,
"tx_bytes": 0,
"tx_packets": 0,
"tx_errors": 0,
"tx_dropped": 0
}
}
}
I was able to calculate the utilization of memory from the data, but I didn't find a way to get the CPU utilization .
And ideas?
You've probably solved this by now, but for the next person... This example is in Python, but the data fields and math are the same if you're making API calls.
The API returns cumulative values, so you need more than one sample - do the math using the difference between samples to get the utilization for that period. This example uses the streaming mode, which pushes an update every second.
# These initial values will seed the "last" cycle's saved values
containerCPU = 0
systemCPU = 0
container = client.containers.get(containerID)
#This function is blocking; the loop will proceed when there's a new update to iterate
for stats in container.stats(decode=True):
#Save the values from the last sample
lastContainerCPU = containerCPU
lastSystemCPU = systemCPU
#Get the container's usage, the total system capacity, and the number of CPUs
#The math returns a Linux-style %util, where 100.0 = 1 CPU core fully used
containerCPU = stats.get('cpu_stats',{}).get('cpu_usage',{}).get('total_usage')
systemCPU = stats.get('cpu_stats',{}).get('system_cpu_usage')
numCPU = len(stats.get('cpu_stats',{}).get('cpu_usage',{}).get('percpu_usage',0))
# Skip the first sample (result will be wrong because the saved values are 0)
if lastContainerCPU and lastSystemCPU:
cpuUtil = (containerCPU - lastContainerCPU) / (systemCPU - lastSystemCPU)
cpuUtil = cpuUtil * numCPU * 100
print(cpuUtil)

Show Series and colorAxis both in Legend

Is it possible to have both colorAxis and series in the legend? http://jsfiddle.net/6k17dojn/ i see i can only show one at a time when I toggle this setting
colorAxis: {
showInLegend: true,
}
Currently to show a basic legend with colorAxis, you need to add some code to Highcharts core. This plugin below allows you to add colorAxis to a legend if showInLegend property is set to false:
(function(H) {
H.addEvent(H.Legend, 'afterGetAllItems', function(e) {
var colorAxisItems = [],
colorAxis = this.chart.colorAxis[0],
i;
if (colorAxis && colorAxis.options) {
if (colorAxis.options.dataClasses) {
colorAxisItems = colorAxis.getDataClassLegendSymbols();
} else {
colorAxisItems.push(colorAxis);
}
}
i = colorAxisItems.length;
while (i--) {
e.allItems.unshift(colorAxisItems[i]);
}
});
}(Highcharts))
Live demo: http://jsfiddle.net/BlackLabel/hs1zeruy/
API Reference: https://api.highcharts.com/highcharts/colorAxis.showInLegend
Docs: https://www.highcharts.com/docs/extending-highcharts
It's possible, but not with the data you currently work with. A heatmap's data is a set of coordinates, but here, your two series overlap.
Your raw data is :
[
[0,0,0.2, 0.4],
[0,1,0.1, 0.5],
[0,2,0.4, 0.9],
[0,3,0.7, 0.1],
[0,4,0.3, 0.6]
]
From there, you're mapping two series: 2018, and 2019 via the seriesMapping: [{x: 0, y: 1, value: 2}, {x: 0, y: 1, value: 3}] option.
You thus end up with the following two series:
2018 2019 2019 should be
[ [ [
[0, 0, 0.2], [0, 0, 0.4], [1, 0, 0.4],
[0, 1, 0.1], [0, 1, 0.5], [1, 1, 0.5],
[0, 2, 0.4], [0, 2, 0.9], [1, 2, 0.9],
[0, 3, 0.7], [0, 3, 0.1], [1, 3, 0.1],
[0, 4, 0.3] [0, 4, 0.6] [1, 4, 0.6]
] ] ]
Notice that in both cases, the coordinates are the same, but for 2019, the x value should be 1. Since you have 0 as x coordinate for both series, they overlap.
To fix you issue, you need to change your data (or pre-process it, whatever is easier). For example:
var data = '[[0,0,0.2, 0.4],[0,1,0.1, 0.5],[0,2,0.4, 0.9],[0,3,0.7, 0.1],[0,4,0.3, 0.6]]';
var rows = JSON.parse(data);
rows = $.map(rows, function(arr){
return [[
arr[0], arr[1], arr[2], // 2018
arr[0] + 1, arr[1], arr[3], // 2019
]];
});
// and the seriesMapping changes to
data: {
rows: rows,
firstRowAsNames: false,
seriesMapping: [{x: 0, y: 1, value: 2}, {x: 3, y: 4, value: 5}]
},
You can see it in action here: http://jsfiddle.net/Metoule/qgd2ca6p/6/

Line not rendered with data in variable but rendering with array data

I have a method which renders a line graph with Highcharts. The data in the graph is an array in the avg_rates variable, which has these values:
[0.8936e2, 0.8901e2, 0.9015e2, 0.9043e2, 0.8994e2, 0.9105e2, 0, 0, 0, 0, 0, 0]
When I use the variable it doesn't render the line:
f.series(
name: "Average rates",
data: avg_rates
)
When I use the array it does render the line:
f.series(
name: "Average rates",
data: [0.8936e2, 0.8901e2, 0.9015e2, 0.9043e2, 0.8994e2, 0.9105e2, 0, 0, 0, 0, 0, 0]
)
I have no ideay why this is happening? Here is the method in full:
def create_avg_rates_chart(avg_rates)
months = ['jan','feb','mar','apr','mei','jun','jul','aug','sep','okt','nov', 'dec']
min = avg_rates[0] - 5
max = avg_rates[0] + 5
avg_rates_chart = LazyHighCharts::HighChart.new('graph') do |f|
f.chart(type: 'line', height: '150', width: '1000')
f.pane(size: '100%')
f.colors(['#0092C9'])
f.xAxis(
categories: months.map{ |m| [m] },
labels: {
style: { "fontSize": "12px" }
}
)
f.yAxis(
title: {
text: 0
},
min: min,
max: max
)
f.plotOptions(
line: {
dataLabels: {
enabled: true,
padding: 10
},
enableMouseTracking: false,
lineWidth: 4,
marker: {
radius: 5
}
}
)
f.series(
name: "Average rates",
data: avg_rates
)
f.legend(enabled: false)
end
end
This most likely happens because when you copied the contents from the array variable you don't copy the actual object but just the console representation (aka the result of #inspect).
The array avg_rates most likely happens to contain BigDecimals:
# avg_rates comes in from outside the function, the line below is a mock.
avg_rates = %w[89.36 89.01 90.15 90.43 89.94 91.05 0 0 0 0 0 0].map(&:to_d)
These values are represented in the console using the #inspect method and produce the following visual output:
#=> [0.8936e2, 0.8901e2, 0.9015e2, 0.9043e2, 0.8994e2, 0.9105e2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
This visual output is also perfectly valid Ruby code. However if you type 0.8936e2 into the console you'll instantiate a Float and not a BigDecimal. This can be seen if you look at the return value of just entering the the representation of the array:
avg_rates_repr = [0.8936e2, 0.8901e2, 0.9015e2, 0.9043e2, 0.8994e2, 0.9105e2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
#=> [89.36, 89.01, 90.15, 90.43, 89.94, 91.05, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
avg_rates.map(&:class).uniq
#=> [BigDecimal]
avg_rates_repr.map(&:class).uniq
#=> [Float]
As you said the graph doesn't render when using the avg_rates variable, but does with the copying the representation. This means that LazyHighCharts::HighChart doesn't accept BigDecimals but does accept Floats. So your solution should be to convert the values to Floats before passing them to the :data option of #series.
data: avg_rates.map(&:to_f)

Lines, circles and other shapes?

Is it possible to draw lines, circles and other shapes with pdfmake? If yes, is there a documentation or are there any samples? I would like to replace jsPDF with pdfmake.
Yes, its possible. pdfmake calls them vectors. See
pdfMake Vector examples for more possibilities.
An example for drawing a line followed by a polygon:
{
canvas:
[
{
type: 'line',
x1: 40, y1: 60,
x2: 260, y2: 60,
lineWidth: 3
},
{
type: 'polyline',
lineWidth: 3,
closePath: true,
points: [{ x: 10, y: 10}, { x: 35, y: 40 }, { x: 100, y: 40 }, { x: 125, y:10 }]
}
]
}
I answered an issue in pdfMake at GitHub like this:
Create a table with layout headeronly you must define an empty body, otherwise the line would not appear:
var dd = {
content: [
{
table : {
headerRows : 1,
widths: [200],
body : [
[''],
['']
]
},
layout : 'headerLineOnly'
}
] }
The width defines the length of the line
canvas: [
{
type: 'rect',
x: 198,
y: -186,
w: 198,
h: 188,
r: 8,
lineWidth: 4,
lineColor: '#276fb8',
},
]
As far as I know, pdfmake does not provide an drawing API. Despite this, pdfmake provides you some methods to insert images at your pdf.
Best regards!

Resources