How can I display a bar chart with multiple series:
http://jsfiddle.net/qyd6w5tx/1/
$(function () {
$('#container').highcharts(
{
"chart": {
"style": {
"fontFamily": "Arial, sans-serif"
},
"alignTicks": false,
"marginRight": 20,
"height": 334
},
"tooltip": {
"pointFormat": "<span style=\"color:{series.color}\">●</span> <span style=\"{series.options.style.pct}\">({point.percentage:,.2f}%)</span> <b style=\"{series.options.style.abs}\">{point.value:,.2f}</b><br/>"
},
"xAxis": {
"type": "category",
"reversed": false,
"labels": {}
},
"yAxis": [{
"title": {
"text": null
},
"index": 0
}, {
"title": {
"text": null
},
"labels": {
"format": "{value}%"
},
"index": 1,
"min": -0.39,
"max": 9.99
}, {
"title": {
"text": null
},
"labels": {
"format": "{value}%"
},
"opposite": true,
"index": 2
}],
"legend": {
"borderWidth": 0,
"enabled": false
},
"plotOptions": {
"bar": {
"dataLabels": {
"enabled": true,
"style": {
"textShadow": "none"
},
"allowOverlap": true
},
"minPointLength": 2
},
},
"credits": {
"enabled": false
},
"series": [{
"name": "Group A",
"type": "bar",
"format": "pct",
"top_value": "",
"min_percent": "",
"style": {
"abs": "display: none"
},
"data": [{
"name": "Test 01",
"value": 0.8,
"percentage": 0.8,
"y": 0.8
}, {
"name": "Test 02",
"value": 2,
"percentage": 2,
"y": 2
}, {
"name": "Test 03",
"value": -0.5,
"percentage": -0.5,
"y": -0.5
}, {
"name": "Test 04",
"value": 2.33,
"percentage": 2.33,
"y": 2.33
}],
"yAxis": 1
}, {
"name": "Group B",
"type": "bar",
"format": "pct",
"top_value": "",
"min_percent": "",
"style": {
"abs": "display: none"
},
"data": [{
"name": "Test 05",
"value": 9,
"percentage": 9,
"y": 9
}, {
"name": "Test 06",
"value": 9,
"percentage": 9,
"y": 9
}, {
"name": "Test 07",
"value": 3,
"percentage": 3,
"y": 3
}],
"yAxis": 1
}],
"title": {
"text": "Test"
}
}
);
});
In this example I would like to display one after the other:
Test 01
Test 02
Test 03
Test 04
Test 05
Test 06
Test 07
And then have the Group A in blue and the Group B in red, and display a legend under the chart with:
- Group A (in blue)
- Group B (in red)
I am bit confused with how to make this with highchart...
Edit:
Thanks to Rotan075 to understand my problem and to find a solution. http://jsfiddle.net/hw5s4ahm/
Actually I didn't specify that need to keep the same data structure for the series:
"series": [{
"name": "Group A",
"type": "bar",
"format": "pct",
"top_value": "",
"min_percent": "",
"style": {
"abs": "display: none"
},
"data": [{
"name": "Test 01",
"value": 0.8,
"percentage": 0.8,
"y": 0.8
}, {
"name": "Test 02",
"value": 2,
"percentage": 2,
"y": 2
}, {
"name": "Test 03",
"value": -0.5,
"percentage": -0.5,
"y": -0.5
}, {
"name": "Test 04",
"value": 2.33,
"percentage": 2.33,
"y": 2.33
}],
"yAxis": 1
}, {
"name": "Group B",
"type": "bar",
"format": "pct",
"top_value": "",
"min_percent": "",
"style": {
"abs": "display: none"
},
"data": [{
"name": "Test 05",
"value": 9,
"percentage": 9,
"y": 9
}, {
"name": "Test 06",
"value": 9,
"percentage": 9,
"y": 9
}, {
"name": "Test 07",
"value": 3,
"percentage": 3,
"y": 3
}],
"yAxis": 1
}]
The rest can change, but this data is generated by a third part level and has to stay generic. I thought it would be just a question of settings but it seem to be much more complicated.
For what I understood out of your code is that you have data for Group A and group B right? What you have to do is make two data list with each of the same length. If there is no data for the specific group you have to add a null value to it. Otherwise Highcharts combines the group A and group B for every Test x.
What you need is this code (live on JSFiddle):
$(function () {
$('#container').highcharts(
{
chart: {
type: 'column',
inverted: true
},
plotOptions: {
series: {
dataLabels: {
enabled: true,
formatter:function() {
if(this.y > 0){
return this.y;
return this.point.y;
}
}
}
}
},
yAxis: {
allowDecimals: false,
min: -1,
labels: {
formatter: function () {
return this.value + '%';
}
},
title: {
text: ' ',
margin:40
}
},
xAxis: {
categories: ['Test1', 'Test2', 'Test3', 'Test4', 'Test5','Test6','Test7']
},
legend: {
enabled: true,
floating: true,
verticalAlign: 'bottom',
align:'middle',
backgroundColor: (Highcharts.theme && Highcharts.theme.legendBackgroundColor) || '#FFFFFF',
borderWidth: 1,
y:10,
x:350
},
series: [{
name: 'GroupA',
color: 'rgba(223, 83, 83, .5)',
data: [{y:null},{y:null}, {y:null}, {y:null}, {y:2.9}, {y:0.5}, {y:1.5}]
},{
name: 'GroupB',
color: 'rgba(119, 152, 191, .5)',
data: [{y:6.5}, {y:3.9}, {y:8.5}, {y:6.6},{y:null},{y:null},{y:null}]
}],
title: {
text: "Test"
}
}
);
});
P.S. For aligning the Legend on the bottom of your graph I did that in a quite hackish way. I use as title text just blank space and place the legend above it. You can modify it in whatever you want.
Most of what you are asking for should be handled by the default behavior of highcharts.
-You can specify the color for each series within the series options:
series: [{
name: 'Group A',
color: 'rgba(0,156,255,0.9)',
data: [...]
},{
name: 'Group B',
color: 'rgba(204,0,0,0.9)',
data: randomData(7)
}]
-You can set your x axis labels via the categories option:
xAxis: {
categories: ['Test 01','Test 02','Test 03','Test 04','Test 05','Test 06','Test 07']
}
-The chart will group them by default
-The legend will be aligned below the chart by default (no hacks required)
Example in action:
http://jsfiddle.net/jlbriggs/3d3fuhbb/57/
Updated example using your data:
http://jsfiddle.net/jlbriggs/3d3fuhbb/58/
Adds a min and max value to the x axis to always show each category
Related
I have created a component for using BarChart and LineChart. When I am hovering on the data points in the said graph, the console is getting filled with errors mentioned below.
Versions Used
"highcharts": "^10.2.0", "highcharts-react-official": "^2.1.3", "react": "^16.8.6",
Sample Image of the Chart
highcharts.src.js:24745 Uncaught TypeError: m.call is not a function
at k.refresh (highcharts.src.js:24745:1)
at g.<anonymous> (highcharts.src.js:28123:1)
at x (highcharts.src.js:1660:1)
at g.firePointEvent (highcharts.src.js:25813:1)
at f.runPointActions (highcharts.src.js:28121:1)
at f.onContainerMouseMove (highcharts.src.js:27678:1)
highcharts.src.js:24745 Uncaught TypeError: m.call is not a function
at k.refresh (highcharts.src.js:24745:1)
at g.<anonymous> (highcharts.src.js:28123:1)
at x (highcharts.src.js:1660:1)
at g.firePointEvent (highcharts.src.js:25813:1)
at f.runPointActions (highcharts.src.js:28121:1)
at g.onMouseOver (highcharts.src.js:26371:1)
at SVGGElement.e (highcharts.src.js:43249:1)
Chart Options
{
"chart": {
"zoomType": "xy",
"spacingTop": 50,
"style": {
"fontFamily": "Work Sans, sans-serif"
},
"alignTicks": true
},
"colors": [
"#4a8cb2",
"#506A78",
"#bbbbbb"
],
"title": {
"text": ""
},
"subtitle": {
"text": ""
},
"xAxis": {
"title": {},
"margin": 25,
"style": {
"top": 10
},
"categories": [
"Country: other",
"USA",
"Malaysia",
"India",
"United Kingdom",
"Switzerland",
"South Africa",
"Singapore",
"New Zealand",
"Scotland",
"China"
]
},
"tooltip": {
"formatter": {}
},
"yAxis": [
{
"title": {
"text": "ABC"
},
"plotLines": [
{
"color": "#D5D5D5",
"opacity": 0.5,
"dashStyle": "Dash",
"width": 2,
"org_score": 10,
"value": 63,
"label": {
"align": "right",
"style": {
"fontWeight": "bold"
},
"text": "Org Moment Score: 63"
},
"zIndex": 2
}
],
"min": null,
"max": null,
"allowDecimals": false,
"showFirstLabel": true,
"showLastLabel": true,
"labels": {},
"opposite": true
},
{
"title": {
"text": "ABC"
},
"allowDecimals": false,
"gridLineWidth": 0
}
],
"plotOptions": {
"column": {
"stacking": "normal",
"pointWidth": 20,
"states": {
"hover": {
"brightness": -0.3
}
},
"dataLabels": {}
},
"series": {
"pointWidth": 15,
"marker": {
"fillColor": "#FFFFFF",
"lineWidth": 2,
"lineColor": null
},
"dataLabels": {}
}
},
"series": [
{
"name": "Lorem Ipsum",
"type": "column",
"yAxis": 1,
"data": [
1,
73,
20,
24,
49,
6,
9,
14,
1,
1,
1
]
},
{
"name": "Ipsum Lorem",
"type": "line",
"color": "#ffdc4c",
"data": [
47,
62,
63,
63,
63,
63,
65,
65,
81,
81,
84
]
}
],
"credits": {
"enabled": false
},
"legend": {
"enabled": true,
"margin": 10
},
"exporting": {
"chartOptions": {
"title": {
"text": "'Lorem Ipsum Lorem Ipsum"
}
},
"enabled": true,
"allowHTML": true,
"sourceWidth": 1200,
"sourceHeight": 400,
"csv": {},
"menuItemDefinitions": {
"label": {
"text": "Show-Hide Data Labels"
}
},
"buttons": {
"contextButton": {
"align": "right",
"y": -45,
"x": -5,
"menuItems": [
"downloadPNG",
"downloadJPEG",
"downloadPDF",
"separator",
"label"
]
}
}
},
"page": "Ipsum Lorem Ipsum"
}
Usage:
<HighchartsReact
highcharts={Highcharts}
options={chart_options}
allowChartUpdate={true}
ref={chart_ref}/>
Props Passed:
highcharts: Highcharts from highcharts/highstock
ref: React.createRef() passed
I have tried searching for the solution to this issue, but all I have gotten so far is that there are some issues related to tooltips. I can't pinpoint the issue, any help would be appreciated.
https://www.highcharts.com/forum/viewtopic.php?t=42956
The issue is caused by the following code:
tooltip: {
formatter: {}
}
In fact, tooltip.formatter is a callback function, so should be put this way:
tooltip: {
formatter: function() {}
}
or omitted if you don't want to format the tooltip.
Demo:
https://codesandbox.io/s/highcharts-react-demo-forked-0syyvk
API:
https://api.highcharts.com/highcharts/tooltip.formatter
I've got the following retool javascript code representing my Plotly data object. It however is producing the bar plot as expected but it is not producing any x-axis labels. I would have thought the string I am doing the groupings (the groupby column is a string) over would be under each column but no luck (just integer increments).
Is there a way to get the list of groups as it is plotted? I can then set that as the "xticks" argument. I tried setting the "type":"categorical" but no dice.
[
{
"name": "foobar",
"y": y_column,
"text": text_column,
"type": "bar",
"transforms": [
{
"type": "groupby",
"groups": group_column,
"styles": []
},
{
"type": "aggregate",
"groups": aggregate_group_column,
"aggregations": [
{
"target": target_variable,
"func": "avg",
"enabled": true
}
]
}
]
}
]
The layout is as follows
{
"title": {
"text": "<br>",
"font": {
"color": "#3D3D3D",
"size": 16
}
},
"font": {
"family": "Inter",
"color": "#979797"
},
"showlegend": true,
"legend": {
"xanchor": "center",
"x": 1,
"y": 1.0,
"orientation": "r"
},
"margin": {
"l": 72,
"r": 24,
"t": 80,
"b": 72,
"pad": 2
},
"hovermode": "closest",
"hoverlabel": {
"bgcolor": "#000",
"bordercolor": "#000",
"font": {
"color": "#fff",
"family": "Inter",
"size": 20
}
},
"clickmode": "select+event",
"dragmode": "select",
"xaxis": {
"title": {
"text":'X-Axis',
"standoff": 15,
"font": {
"size": 20
}
},
"type": "linear",
"tickformat": "",
"automargin": true,
"fixedrange": true,
"gridcolor": "#fff",
"zerolinecolor": "#fff",
"tickmode":'array'
},
"yaxis": {
"title": {
"text": variable_name,
"standoff": 6,
"font": {
"size": 20
}
},
"type": "linear",
"tickformat": "",
"automargin": true,
"fixedrange": true,
"zerolinecolor": "#DEDEDE"
}
}
If I have multiple charts, say a stacked bar and a pie chart on my page. I would like to interact (e.g. click) on one of it and see some visual update on the other chart.
I tried creating them using FusionCharts in the following manner:
FusionCharts.ready(function() {
var pieChart = new FusionCharts({
type: 'pie2d',
renderAt: 'pieContainer',
width: '400',
height: '300',
dataFormat: 'json',
dataSource: {
"chart": {
"caption": "Company Revenue",
"enableMultiSlicing": "0",
"bgcolor": "FFFFFF",
"showvalues": "1",
"showpercentvalues": "1",
"showborder": "0",
"showplotborder": "0",
"showlegend": "1",
"legendborder": "0",
"legendposition": "bottom",
"enablesmartlabels": "1",
"use3dlighting": "0",
"showshadow": "0",
"legendbgcolor": "#CCCCCC",
"legendbgalpha": "20",
"legendborderalpha": "0",
"legendshadow": "0",
"legendnumcolumns": "3",
"palettecolors": "#f8bd19,#e44a00,#008ee4,#33bdda,#6baa01,#583e78"
},
"data": [{
"label": "Services",
"value": "26"
}, {
"label": "Hardware",
"value": "32"
}, {
"label": "Software",
"value": "42"
}]
}
}).render();
var stackedBar = new FusionCharts({
type: 'stackedBar2D',
renderAt: 'barContainer',
width: '400',
height: '300',
dataFormat: 'json',
dataSource: {
"chart": {
"caption": "Company Revenue",
"xaxisname": "Month",
"yaxisname": "Revenue",
"bgcolor": "FFFFFF",
"outcnvbasefontcolor": "666666",
"numberprefix": "$",
"showvalues": "0",
"numvdivlines": "10",
"showalternatevgridcolor": "1",
"alternatevgridcolor": "e1f5ff",
"divlinecolor": "e1f5ff",
"vdivlinecolor": "e1f5ff",
"basefontcolor": "666666",
"tooltipbgcolor": "F3F3F3",
"tooltipbordercolor": "666666",
"canvasbordercolor": "666666",
"canvasborderthickness": "1",
"showplotborder": "1",
"plotfillalpha": "80",
"showborder": "0",
"legendbgcolor": "#CCCCCC",
"legendbgalpha": "20",
"legendborderalpha": "0",
"legendshadow": "0",
"legendnumcolumns": "3"
},
"categories": [{
"category": [{
"label": "Jan"
}, {
"label": "Feb"
}, {
"label": "Mar"
}, {
"label": "Apr"
}, {
"label": "May"
}, {
"label": "Jun"
}, {
"label": "Jul"
}, {
"label": "Aug"
}, {
"label": "Sep"
}, {
"label": "Oct"
}, {
"label": "Nov"
}, {
"label": "Dec"
}]
}],
"dataset": [{
"seriesname": "Product A",
"data": [{
"value": "27400"
}, {
"value": "29800"
}, {
"value": "25800"
}, {
"value": "26800"
}, {
"value": "29600"
}, {
"value": "32600"
}, {
"value": "31800"
}, {
"value": "36700"
}, {
"value": "29700"
}, {
"value": "31900"
}, {
"value": "34800"
}, {
"value": "24800"
}]
}, {
"seriesname": "Product B",
"data": [{
"value": "10000"
}, {
"value": "11500"
}, {
"value": "12500"
}, {
"value": "15000"
}, {
"value": "11000"
}, {
"value": "9800"
}, {
"value": "11800"
}, {
"value": "19700"
}, {
"value": "21700"
}, {
"value": "21900"
}, {
"value": "22900"
}, {
"value": "20800"
}]
}],
"trendlines": [{
"line": [{
"startvalue": "42000",
"color": "91C728",
"displayvalue": "Target",
"showontop": "1"
}]
}],
"styles": {
"definition": [{
"name": "CanvasAnim",
"type": "animation",
"param": "_xScale",
"start": "0",
"duration": "1"
}],
"application": [{
"toobject": "Canvas",
"styles": "CanvasAnim"
}]
}
}
}).render();
});
<script src="http://static.fusioncharts.com/code/latest/fusioncharts.js"></script>
<div>
<span id="barContainer">FusionCharts XT will load here!</span>
<span id="pieContainer">FusionCharts XT will load here!</span>
</div>
Now how to update the other chart on interacting one of the chart? Say by clicking or hovering plots on one of the chart, has its visual update in another chart.
**Note: ** The data is not relevant in this case. Only the chart to chart interactivity needs to be established. There is no restriction on JS library being used and can be entirely based on the responder choice.Any help is highly appreciable.
With highcharts, you could override the click function, then update whichever properties you want.
See: http://api.highcharts.com/highcharts#chart.events
I do not know how it is with FusionCharts, although I think syncing data between different type of charts should be possible, but I was using a lot amCharts and if you have no restriction on library then I put this quick tips link to show you what you can fairly quickly implement there.
http://www.amcharts.com/tips/automatically-syncing-pie-chart-data-column-chart-hover/
Is it possible to stack data hourly ? I have only two columns: time and signal from trigger "trig = 1". So I need to stack all trigger signals on each hour. So on Y axis should be a number sum of all trigger signals in each hour. You can use this example JSFiddle.
Data looks like this:
[{"time":"15:15:00","trig":"1"},{"time":"15:45:00","trig":"1"},
{"time":"16:10:18","trig":"1"},{"time":"16:20:00","trig":"1"},
{"time":"17:30:00","trig":"1"},{"time":"17:50:00","trig":"1"},
{"time":"18:25:00","trig":"1"},{"time":"18:45:00","trig":"1"},
{"time":"19:05:00","trig":"1"},{"time":"19:40:00","trig":"1"},
{"time":"21:15:00","trig":"1"},{"time":"21:50:00","trig":"1"}]
And my JS:
var chart = AmCharts.makeChart( "chartdiv", {
"type": "stock",
"dataSets": [{
"title": "triger",
"fieldMappings": [{
"fromField": "time",
"toField": "time"
}, {
"fromField": "trig",
"toField": "trig"
}],
"compared": false,
"categoryField": "time",
"dataLoader": {
"url": "values4.php",
"format": "json",
"showCurtain": true,
"showErrors": true,
"async": true,
"reverse": true,
"delimiter": ",",
"useColumnNames": true
}
}],
"pathToImages": "images/",
"dataDateFormat": "JJ:NN:SS",
"categoryAxis": {
"parseDates": true
},
"panels": [{
"legend": {},
"stockGraphs": [{
"id": "graph1",
"valueField": "trig",
"type": "column",
"title": "MyGraph",
"fillAlphas": 1
}]
}],
"periodSelector": {
"position": "top",
"dateFormat": "JJ:NN",
"inputFieldWidth": 150,
"periods": [ {
"period": "hh",
"count": 1,
"label": "1 hour",
"selected": true
}, {
"period": "hh",
"count": 2,
"label": "2 hours"
}, {
"period": "hh",
"count": 5,
"label": "5 hour"
}, {
"period": "hh",
"count": 12,
"label": "12 hours"
}, {
"period": "MAX",
"label": "MAX"
} ]
},
"panelsSettings": {
"usePrefixes": true
},
"export": {
"enabled": true,
"position": "bottom-right"
},
"categoryAxesSettings": {
"maxSeries": 1,
"groupToPeriods": ["5ss"]
},
"periodSelector": {
"position": "top",
"inputFieldsEnabled": false,
"periods": [{
"period": "HH",
"count": 1,
"label": "1 hour"
}, {
"period": "HH",
"count": 12,
"label": "12 hours"
}, {
"period": "MAX",
"selected": true,
"label": "MAX"
}]
},
});
I've been playing around with Vega, but I can't get my head around how to turn a vertical bar chart into an horizontal bar chart.
A similar question was posted a while ago here: vega horizontal bar charts but the provided answer isn't very clear on what exactly is being done to the code to produce the desired result. I also haven't been able to get the solution to run!
My understanding for now is that you need to switch the X and Y axis and scales, but where I get lost is in getting the mark to be flipped as well? I've tried setting the "x" and "y" attributes but I just get a blank chart in return... It really feels like I'm only missing one thing as my axes are right, but can't figure what it is!
EDIT: made some progress! My columns are now appearing, but their position is weirdly shifted vs the actual ticks. I've looked into adjusting the "points" parameter of the ordinal scale, but as a result the last column
The plot I obtain right now.
And with the "points" parameter set to true for the y scale.
Here's the code I have so far below
{
"width": 400,
"height": 400,
"padding": {
"top": 30,
"left": 40,
"bottom": 30,
"right": 10
},
"data": [
{
"name": "table",
"values": [
{
"x": "Mon",
"y": 2
},
{
"x": "Tue",
"y": 3
},
{
"x": "Wed",
"y": 10
}
]
}
],
"scales": [
{
"name": "x",
"type": "ordinal",
"points": true
"range": "height",
"zero": false,
"domain": {
"data": "table",
"field": "x"
}
},
{
"name": "y",
"type": "linear",
"range": "width",
"domain": {
"data": "table",
"field": "y"
},
"nice": true
}
],
"axes": [
{
"type": "x",
"scale": "y"
},
{
"type": "y",
"scale": "x"
}
],
"marks": [
{
"type": "rect",
"from": {
"data": "table"
},
"properties": {
"enter": {
"x": {
"scale": "y",
"field": "y"
},
"x2": {
"value": 0
},
"yc": {
"scale": "x",
"field": "x"
},
"height": {
"value": 40
},
"fill": {
"r": {
"value": 66
},
"g": {
"value": 190
},
"b": {
"value": 244
}
}
}
}
}
]
}
Victory!
Here's a working spec!
I used the "padding" property of the ordinal scale to get the desired result.
{
"width": 400,
"height": 400,
"padding": {
"top": 30,
"left": 40,
"bottom": 30,
"right": 10
},
"data": [
{
"name": "table",
"values": [
{
"x": "Mon",
"y": 2
},
{
"x": "Tue",
"y": 3
},
{
"x": "Wed",
"y": 10
}
]
}
],
"scales": [
{
"name": "x",
"type": "ordinal",
"range": "height",
"points": true,
"padding": 1,
"zero": false,
"domain": {
"data": "table",
"field": "x"
}
},
{
"name": "y",
"type": "linear",
"range": "width",
"domain": {
"data": "table",
"field": "y"
},
"nice": true
}
],
"axes": [
{
"type": "x",
"scale": "y"
},
{
"type": "y",
"scale": "x"
}
],
"marks": [
{
"type": "rect",
"from": {
"data": "table"
},
"properties": {
"enter": {
"x": {
"scale": "y",
"field": "y"
},
"x2": {
"value": 0
},
"yc": {
"scale": "x",
"field": "x"
},
"height": {
"value": 40
},
"fill": [
66,
190,
244
]
}
}
}
]
}