I need to display data points in a scatter plot using c3.js. The data points arrive in batches, and I want to update the plot incrementally as the new points arrive.
The first batch is given while initializing the plot, and displays fine. But when I use flow to update the plot, the earlier points get erased. Also, the X axis does not display the correct X coordinates. [Edit: added clarification] After the flow, the points appear at (3, 1), (4, 1), (5, 1) and not (1.5, 1), (2.5, 1), (3.5, 1) as specified in the data.]
Am I missing something?
JsFiddle: http://jsfiddle.net/cornea/b33usb69/
var chart = c3.generate({
data: {
x: 'A',
columns: [
['A', 1.5, 2.5, 3.5],
['B', 2.0, 2.0, 2.0]
],
type: 'scatter',
types: { 'B': 'scatter' }
},
axis: {
x: { label: 'A', tick: { fit: true } },
y: { label: 'B' }
}
});
setTimeout(function () {
chart.flow({
columns: [
['A', 1.5, 2.5, 3.5],
['B', 1.0, 1.0, 1.0]
]
});
}, 2000);
Thanks.
Not sure why you're using .flow, isn't that more for time-series data?
Can't you just use .load to get the new data points onto the chart?
Like so: http://jsfiddle.net/b33usb69/20/
EDIT:
If you want it in the same array, then something like this:
(code not tested)
var a = ['A_x', 1.5, 2.5, 3.5], b = ['A', 2.0, 2.0, 2.0];
var chart = c3.generate({
data: {
xs: { A: 'A_x' },
columns: [
['A_x', 1.5, 2.5, 3.5],
['A', 2.0, 2.0, 2.0]
],
type: 'scatter'
},
axis: {
y: { min: 0, max: 3 }
}
});
setTimeout(function () {
a = a.concat[1.5, 2.5, 3.5];
b = b.concat[1.0, 1.0, 1.0];
chart.load({
columns: [
a,
b
]
});
}, 2000);
Because the scale of your Y axis shifts so much in your example (a 50% drop in the values) you will probably need to set axis: { y: { min: 0 }, y: { max: 2 } } to see the scatter points move. Try this jsfiddle to see if that change does what you want.
The X axis values are updated when you use chart.flow if you change that to load and reload the chart data with chart.load({ ... }) they will stay the same. To get a chart to flow data properly there's a little more work required to initialize the X axis values (see the flow API example) but it's not clear from your simple example that this is what you want to do.
Edit:
Thanks for your clarification. I can't answer your question with working code but see github #865 issue for C3.js which is related to your problem.
You might want to consider using a different approach to the data and avoiding flow in order to construct a suitable chart.
Related
Is it possible to make echarts line chart with 1 line painted in different colors? For example if value <= 0 the color is red, if > 0 the color is green?
Echarts has an option called visualMap that does exactly what you are looking for.
visualMap doc
visualMap code example (I selected the example that fits best, but there are others)
In your case you'll have something like that :
visualMap: {
show: false, // Wether to show the legend or not (default: true)
pieces: [
{
min: -9999, // Normally not needed but doesn't work without that (1)
max: 0,
color: '#F35E07' // Red
},
{
min: 0,
color: '#93CE07' // Green
},
],
outOfRange: {
color: '#F35E07'
}
},
It'll split your line in 2 pieces :
below 0 (written max: 0) : red
above 0 (written min: 0) : green
In addition, the visualMap option has more to offer : you can have more than 2 pieces (like in this example), have a smooth gradient instead of pieces (using type: 'continuous' like in this example), and many other things that are explained in its doc.
(1) Note about the bug: Normally if you don't specify min or max,
it's set to -Infinity or Infinity. But here you have to specify
min AND max in one of the two pieces (I don't know why).
If you consider plotting two charts and ignoring some of its points with '-', you can achieve the same visual result of a multicolored line chart.
Although the documentation does not provide an immediate example of how to color specific segments of a line chart, it actually instructs about how you can use empty data,
While there are empty elements, the lines chart will ignore that point without passing through it----empty elements will not be connected by the points next. In ECharts, we use '-' to represent null data, It is applicable for data in other series.
With that in mind, by overlaying two equal charts and emptying some points, you can actually construct the logic of a multicolored chart. Notice that it is better if you can do it programmatically so that you can vary the number of line segments to be colored.
var chartDom = document.getElementById('main');
var myChart = echarts.init(chartDom);
var option;
option = {
xAxis: {},
yAxis: {},
series: [
{
data: [
[-20, -20],
[-10, 30],
[0, 40],
['-', '-'],
['-', '-']
],
type: 'line',
lineStyle: {
color: "red"
}
},
{
data: [
['-', '-'],
['-', '-'],
[0, 40],
[10, 100],
[20, 60]
],
type: 'line',
lineStyle: {
color: "green"
}
}
]
};
option && myChart.setOption(option);
.as-console-wrapper { max-heght: 100% !important }
<script src="https://cdn.jsdelivr.net/npm/echarts#5.3.2/dist/echarts.js"></script>
<body>
<div id="main" style="width: 225px;height:225px;"></div>
</body>
I'm trying to make a radar chart using quickchart.io. I accomplished the look I want on raw html, but for some reason, quickchart doesn't like it when it comes to radial option :(
{
type: 'radar',
data: {
labels: ['A', 'B', 'C', 'D', 'E'],
datasets: [
{
data: [5, 4, 3, 3, 5],
label: 'Dataset'
},
{
data: [5, 4, 5, 3, 2],
label: 'Dataset 2'
}
],
},
options: {
scales: {
r: [
{
min:'0',
max:'5',
ticks: {
stepSize: '1'
},
},
],
}
},
}
It looks like it's totally ignoring everything in options. As you can see, I want the chart always start from 0 and tick mark increased by 1. Here's the result of the code above:
https://quickchart.io/chart?c=%7B%0A%20%20type%3A%20%27radar%27%2C%0A%20%20data%3A%20%7B%0A%20%20%20%20labels%3A%20%5B%27A%27%2C%20%27B%27%2C%20%27C%27%2C%20%27D%27%2C%20%27E%27%5D%2C%0A%20%20%20%20datasets%3A%20%5B%0A%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20data%3A%20%5B5%2C%204%2C%203%2C%203%2C%205%5D%2C%0A%20%20%20%20%20%20%20%20label%3A%20%27Dataset%27%0A%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20data%3A%20%5B5%2C%204%2C%205%2C%203%2C%202%5D%2C%0A%20%20%20%20%20%20%20%20label%3A%20%27Dataset%202%27%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%5D%2C%0A%20%20%7D%2C%0A%20%20options%3A%20%7B%0A%20%20%20%20scales%3A%20%7B%0A%20%20%20%20%20%20r%3A%20%5B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20min%3A%270%27%2C%0A%20%20%20%20%20%20%20%20%20%20max%3A%275%27%2C%0A%20%20%20%20%20%20%20%20%20%20ticks%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20stepSize%3A%20%271%27%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%7D%0A
Can anyone help me?
You are trying to use v3 syntax but you are using it incorrect, the scales dont use arrays anymore. You also have to specify to quickchart you are using v3 like so https://quickchart.io/chart?version=3&c=CHARTCONFIG
Correct scale config V3 for you:
scales: {
r:{
min:'0',
max:'5',
ticks: {
stepSize: '1'
},
},
}
Working url based on your sample:
https://quickchart.io/chart?version=3&c=%7B%0D%0A%20%20type%3A%20%27radar%27%2C%0D%0A%20%20data%3A%20%7B%0D%0A%20%20%20%20labels%3A%20%5B%27A%27%2C%20%27B%27%2C%20%27C%27%2C%20%27D%27%2C%20%27E%27%5D%2C%0D%0A%20%20%20%20datasets%3A%20%5B%0D%0A%20%20%20%20%20%20%7B%0D%0A%20%20%20%20%20%20%20%20data%3A%20%5B5%2C%204%2C%203%2C%203%2C%205%5D%2C%0D%0A%20%20%20%20%20%20%20%20label%3A%20%27Dataset%27%0D%0A%20%20%20%20%20%20%7D%2C%0D%0A%20%20%20%20%20%20%7B%0D%0A%20%20%20%20%20%20%20%20data%3A%20%5B5%2C%204%2C%205%2C%203%2C%202%5D%2C%0D%0A%20%20%20%20%20%20%20%20label%3A%20%27Dataset%202%27%0D%0A%20%20%20%20%20%20%7D%0D%0A%20%20%20%20%5D%2C%0D%0A%20%20%7D%2C%0D%0A%20%20options%3A%20%7B%0D%0A%20%20%20%20scales%3A%20%7B%0D%0A%20%20%20%20%20%20r%3A%20%0D%0A%20%20%20%20%20%20%20%20%7B%0D%0A%20%20%20%20%20%20%20%20%20%20min%3A%270%27%2C%0D%0A%20%20%20%20%20%20%20%20%20%20max%3A%275%27%2C%0D%0A%20%20%20%20%20%20%20%20%20%20ticks%3A%20%7B%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20stepSize%3A%20%271%27%0D%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%0D%0A%20%20%20%20%20%20%20%20%7D%2C%0D%0A%20%20%20%20%7D%0D%0A%20%20%7D%2C%0D%0A%7D
quickchart.io defaults to latest Chart.js v2 according to their documentation. Therefore, your chart options need to be written as follows. Alternatively you can try to define the version parameter to explicitly tell quickchart.io to use Chart.js v3.
options: {
scale: {
ticks: {
suggestedMin: 0,
suggestedMax: 5,
stepSize: '1'
}
}
}
For further details about the latest Chart.js v2 radar charts, please consult https://www.chartjs.org/docs/2.9.4/charts/radar.html
I'm having hard time adding the dial/needle to the gauge chart from plotly.js.
gauge without needle
: As you could see in the image above it's gauge chart without any needle.
gauge with needle
: I want to build something similar to "gauge with needle", which is giving me hard time.
my code for "gauge without needle/dial" :
`https://codepen.io/vivek137/pen/rNyembX`
You will need to add an arrow annotation on top of your gauge chart. I answered a similar question and in that answer, I described how you can use polar coordinates to find out the ending position x and y for your arrow. Under the hood, the gauge chart you made has an x-range of [0,1] and a y-range of [0,1], so the starting point is ax=0.5 and ax=0 which are both parameters for your annotation. Then the ending position is given by x = 0.5 + r * cos(theta) and y = r * sin(theta) where theta is the angle taken from the right side of the chart and moving counterclockwise.
One thing you should keep in mind is that if the render area in your browser isn't a perfect square, then the r and theta values may need to be adjusted. For example, in my codepen, I used r=0.7, theta=93.5 to point to the 40.
let data = [
{
mode: "gauge",
type: "indicator",
value: 40,
gauge: {
shape: "angular",
bar: {
color: "blue",
line: {
color: "red",
width: 4
},
thickness: 0
},
bgcolor: "#388",
bordercolor: "#a89d32",
borderwidth: 3,
axis: {
range: [0,100],
visible: true,
tickmode: "array",
tickvals: [5, 10, 40, 80, 100],
ticks: "outside"
},
steps: [
{
range: [0, 40],
color: "#9032a8"
}
]
}
}
]
var theta = 93.5
var r = 0.7
var x_head = r * Math.cos(Math.PI/180*theta)
var y_head = r * Math.sin(Math.PI/180*theta)
let layout = {
xaxis: {range: [0, 1], showgrid: false, 'zeroline': false, 'visible': false},
yaxis: {range: [0, 1], showgrid: false, 'zeroline': false, 'visible': false},
showlegend: false,
annotations: [
{
ax: 0.5,
ay: 0,
axref: 'x',
ayref: 'y',
x: 0.5+x_head,
y: y_head,
xref: 'x',
yref: 'y',
showarrow: true,
arrowhead: 9,
}
]
};
Plotly.newPlot('gauge1', data, layout)
I have data to display on c3.js graph and there is one piece of data which is smaller than other ones.
For exmaple A can by 140 000, B 20 000 and C 700. C can even be negative.
The problem is that when I display my data on the chart you can't really see the dynamics of C because its' values are too little for scale of the graph. If C is negative it doesn't show on the graph at all.
Is there some way to scale the graph that way so all data displayed properly?
const chartConfig = {
bindto: $element.find('.canvas')[0],
data: {
json: [],
keys: { value: [] },
type: 'line'
},
grid: {
x: {
get: getXGrid
}
},
axis: {
y: { min: 0 },
x: {
tick: {
culling: false,
format: formatXAxis
}
},
y2: {
padding: {top: 0, bottom: 0},
min : 0,
max : 100,
tick : {
format: (value) => `${value}%`
}
}
}
};
Later in one of my methods I set Y max to be the biggest number in data.
chartConfig.axis.y.max = getRoundMax(chartConfig.data);
UPD link
You must be looking for logarithmic scale.
At this moment c3.js does not support for it out-of-the-box.
But there are some workarounds at github:
First, they convert values:
data_test_original = ['data1', 140000, 20000, 700, 10, 100, 1000, 3, 500, 50, 5, 3000]
data_test = ['data1'];
for(var i=1; i<data_test_original.length; i++){
data_test[i] = Math.log(data_test_original[i]) / Math.LN10;
}
Then, they use it alongside with adjusted Y-axis:
c3.generate({
data: {
...
columns: [ data_test ]
},
...
axis : {
y : {
tick: {
format: function (d) { return Math.pow(10,d).toFixed(0); }
}
}
}
});
See full example here or there. Hope this will suit your needs.
I'm using flot library and I found from the docs that I can send a json object with any option I can right at the charting call.
So let's say I call:
$.plot($("#placeholder"), [ [] ], { yaxis: { show: true, max: 100, min: -100 }, xaxis: { show: true, max: 100, min: -100} });
However this is what I get as result (with a non empty data argument):
But I don't want vertical lines marked at every axis tick, but two lines corresponding to the axis.
I don't want ending with the x=0 and y=0 plots. I would even have to obtains points arrays for it. How can I do this with flot or is there any recommended library to plot x,y points series with not much thrills.
To get lines on the axes, add this to your options object:
grid: { markings: [{ xaxis: { from: 0.0, to: 0.0 }, color: 'black', lineWidth: 1 },
{ yaxis: { from: 0.0, to: 0.0 }, color: 'black', lineWidth: 1 }] };
If the other lines are still present after adding this, please provide a more complete example (e.g. a fiddle).