Related
I am trying to create a donut chart with chart.js using data from csv file. Following is my script so far, but it is not working. Any guidance is appreciated on the same.
<script>
var file='donut.csv';
d3.csv(file).then(makeChart); //use d3.csv to read file
function makeChart(types){
var can=types.map(function(d){return d.cancelled});
var suc=types.map(function(d){return d.success});
var fa=types.map(function(d){return d.failed});
{
var chart=new Chart(document.getElementById("doughnut-chart"), {
type: 'doughnut',
data: {
labels: ["Cancelled","Success", "Failed"],
datasets: [
{
label: "Population (millions)",
backgroundColor: ["#3e95cd", "#3cba9f","#8e5ea2"],
data: [can,suc,fa]
}
]
},
options: {
title: {
display: true,
text: 'Weekly Status'
}
}
}
}
);
</script>
and my donut.csv looks like as below:
cancelled,300,
success,1000,
failed,20,
Since your CSV data has no header, you should use d3.text to load the data, followed by d3.csvParseRows to parse it to a JSON array (see https://stackoverflow.com/a/13870360/2358409). To extract the data values from the JSON array, you can use Array.map.
data: d3.csvParseRows(types).map(v => v[1])
Please take a look at your amended code and see how it works.
d3.text("https://raw.githubusercontent.com/uminder/testdata/main/so/csv/donut.csv").then(makeChart);
function makeChart(types) {
new Chart('doughnut-chart', {
type: 'doughnut',
data: {
labels: ['Cancelled', 'Success', 'Failed'],
datasets: [{
label: 'Population (millions)',
backgroundColor: ['#3e95cd', '#3cba9f', '#8e5ea2'],
data: d3.csvParseRows(types).map(v => v[1])
}]
},
options: {
title: {
display: true,
text: 'Weekly Status'
}
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
<canvas id="doughnut-chart" height="90"></canvas>
I'm trying to use chart.js to create a bar chart that shows the number of ad impressions in an ad buy by publication. The desired chart would show a bar for each publication representing the number of impressions for the ad on that website.
I thought that this needs to happen as multiple datasets, one for each publication, where each dataset contains one data point. Here's the code I'm using for this approach:
var chartData_webbanner_300x600 = {
labels: ["Publication 1", "Publication 2"],
datasets: [
{
label: "Publication 1",
backgroundColor: "#971317",
data: [30000]
},
{
label: "Publication 2",
backgroundColor: "#0b72ba",
data: [40000]
},
]
};
window.onload = function() {
var ctx_webbanner_300x600 = document.getElementById('chart_webbanner_300x600').getContext('2d');
window.myBar = new Chart(ctx_webbanner_300x600, {
type: 'bar',
data: chartData_webbanner_300x600,
options: {
title: {
display: true,
text: 'Web Banner Impressions'
},
responsive: true,
}
});
}; //window.onload = function()
The resulting chart only shows one bar. Here's a screenshot:
I also tried this as a single dataset, but had no luck there. This is the approach I tried with that:
var chartData_webbanner_300x600 = {
labels: ["Total Impressions"],
datasets: [
{
label: ["Publication 1", "Publication 2"],
backgroundColor: ["#971317","#0b72ba"],
data: [30000,40000]
}
]
};
window.onload = function() {
var ctx_webbanner_300x600 = document.getElementById('chart_webbanner_300x600').getContext('2d');
window.myBar = new Chart(ctx_webbanner_300x600, {
type: 'bar',
data: chartData_webbanner_300x600,
options: {
title: {
display: true,
text: 'Web Banner Impressions'
},
responsive: true,
}
});
}; //window.onload = function()
Here's how that is displaying (with no bars):
Please let me know if you have any ideas on what I'm doing wrong. Thank you for taking the time to help!
I was able to get it working with this code:
var graphData = {
labels: ['Publication 1', 'Publication 2'],
datasets: [{
label: 'Impressions',
data: [30000, 40000],
backgroundColor: [
"#971317",
"#0b72ba"
],
}, ]
};
var ctx_webbanner_300x600 = document.getElementById('chart_webbanner_300x600').getContext('2d');
var chr = new Chart(ctx_webbanner_300x600, {
data: graphData,
type: 'bar',
options: {
scales: {
yAxes: [{
display: true,
ticks: {
beginAtZero: true // minimum value will be 0.
}
}]
}
}
});
This is based on what I found here Setting specific color per label in chart.js and here How to set max and min value for Y axis - which overcame a problem where the scale was starting at the lowest value in my data set.
I have few charts ready in chart.js. I am trying to put the data that I have fetched through JSON file. How do I change the chart data automatically in a chart? I am getting json data from URL.
chartData1:{
labels: ["01 Jan","02 Jan","03 Jan","04 Jan","05 Jan","06
Jan","07 Jan"],
datasets: [{
label: "s1",
data:
[100,0,1,0,0,1,0,0,0,1,2,3,0,0,0,0,1,1,1,0,0,0,2,1,1,0,1,3,2,1,0],
fill:false,
borderColor: 'Orange',
lineTension:0,
borderWidth:2,
radius:2
},
{
label: "s2",
data:
[2,3,4,1,4,5,3,2,0,1,0,3,5,6,3,7,2,0,5,3,1,2,3,1,0,5,4,5,8,6,2],
fill:false,
borderColor: 'Violet',
lineTension:0,
borderWidth:2,
radius:2
}
]
},
"line-chart" is the id of the <canvas> where you want to display chart.
Try with this.
var chart1 = document.getElementById("line-chart").getContext("2d");
window.myLine = new Chart(chart1).Line(chartData1, {
responsive: true,
scaleLineColor: "rgba(0,0,0,.2)",
scaleGridLineColor: "rgba(0,0,0,.05)",
scaleFontColor: "#c5c7cc"
});
Input data
Engine,Car,Brand,Efficiency
ABC212,Toyota Corolla,Toyota,1.95
ABC212,Toyota Yaris,Toyota,1.94
ABC212,Totyota Etios,Toyota,1.93
ABC212,Honda City,Honda,1.93
ABC212A,Honda Brio,Honda,1.91
DEF311,Toyota Camry,Toyota,1.90
DEF310,Toyota Prius,Toyota,1.82
DEF310,Ford Explorer,Ford,1.85
DEF310,Ford Endeavour,Ford,1.83
DEF305,Ford Fugo,Ford,1.79
With data like above, I need to create a chart in ChartJs with multi-level x-axes. An expected output created using MS excel pivot chart is as below. Here the efficiency of each model is plotted as a bar. Bars in each group is sorted in the descending order of the efficiency value. How should I create the data for this kind of chart ?
I have made such graph in my POC , where I used :
data: {
labels: ["ABC212", "ABC212A",...],
datasets: [
{
label: "ABC212",
data: [val1, val2,....]
}, {
label: "ABC212A",
data: [val3, val4,...]
}
]
}
Without being confident that this is the simplest solution, I provide some example where I use a second axis, containing labels for the groups, but in a scaled-up array, for correct alignment.
The only problem is that if you enable rotation for the group maxRotation>0, the text will always be rotated, since (due to scaling) it is bound to a very small area.
https://jsfiddle.net/h6z4apvo/
var myData = [
["ABC212","Toyota Corolla","Toyota",1.95],
["ABC212","Toyota Yaris","Toyota",1.94],
["ABC212","Totyota Etios","Toyota",1.93],
["ABC212","Honda City","Honda",1.93],
["ABC212A","Honda Brio","Honda",1.91],
["DEF311","Toyota Camry","Toyota",1.90],
["DEF310","Toyota Prius","Toyota",1.82],
["DEF310","Ford Explorer","Ford",1.85],
["DEF310","Ford Endeavour","Ford",1.83],
["DEF305","Ford Fugo","Ford",1.79]
];
/*Calculates group labels to a scaled array so that they can align better*/
function calculateGroupLabels(data){
const scaleFactor=100;
var labels = _(data)
.groupBy((elem)=>elem[0])
.map((entriesOnSameGroup, key)=>{
var newSize = entriesOnSameGroup.length*scaleFactor;
var newArray = new Array(newSize);
newArray[0]="";
newArray[newArray.length-1]="";
newArray[parseInt((newArray.length-1)/2)]=key;
return newArray;
}).flatten().value()
return labels;
}
var labels = calculateGroupLabels(myData);
var ctx = $("#c");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
datasets: [{
label: '# of Votes',
xAxisID:'modelAxis',
data: myData.map((entry)=>entry[3])
}]
},
options:{
scales:{
xAxes:[
{
id:'modelAxis',
type:"category",
ticks:{
//maxRotation:0,
autoSkip: false,
callback:function(label, x2, x3, x4){
console.log("modelAxis", label, x2, x3, x4)
return label;
}
},
labels:myData.map((entry=>entry[1]))
},
{
id:'groupAxis',
type:"category",
gridLines: {
drawOnChartArea: false,
},
ticks:{
padding:0,
maxRotation:0,
autoSkip: false,
callback:function(label){
return label;
}
},
labels:labels
}],
yAxes:[{
ticks:{
beginAtZero:true
}
}]
}
}
});
I have a doughnut graph created using Chart.js with two datasets. The graph displays the number of employees in offices around the world, with the second dataset breaking this down into permanent and contract employees.
There's a jsfiddle of this running here: https://jsfiddle.net/tetsujin1979/tt3ch8z7/
The "labels" attribute of the options for the graph contains the names of the offices, but since there is only one array of labels, they are repeated for the second dataset, and appear on the mouseover text for it.
var config = {
type: 'doughnut',
data: {
datasets: [
{
data: [124,231,152,613,523],
backgroundColor: [chartColors.red, chartColors.orange, chartColors.yellow, chartColors.green, chartColors.blue],
label: 'Offices'
},
{
data: [60,64,100,131,71,81,337,276,405,118],
backgroundColor: [chartColors.purple, chartColors.grey],
label: 'Permanent/Contract'
}
],
labels: ['London', 'New York', 'Paris', 'Moscow', 'Mumbai']
}
};
var ctx = document.getElementById('employees-graph').getContext('2d');
var employeesGraph = new Chart(ctx, config);
Is it possible to specify a second array of labels for the permanent/contract dataset so the hover text displays the values from this second
Add a labels array to both of the datasets
var config = {
type: 'doughnut',
data: {
datasets: [
{
data: [124,231,152,613,523],
backgroundColor: [chartColors.red, chartColors.orange, chartColors.yellow, chartColors.green, chartColors.blue],
label: 'Offices',
labels: ['London', 'New York', 'Paris', 'Moscow', 'Mumbai']
},
{
data: [60,64,100,131,71,81,337,276,405,118],
backgroundColor: [chartColors.purple, chartColors.grey],
label: 'Permanent/Contract',
labels: ['aaa', 'bbb', 'ccc', 'ddd', 'eee']
}
]
}
};
And add the following to the options:
options: {
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
var dataset = data.datasets[tooltipItem.datasetIndex];
var index = tooltipItem.index;
return dataset.labels[index] + ": " + dataset.data[index];
}
}
}
}