NVD3 - Show all tick values - d3.js

My chart needs to have tick values in multiples of 3. For example, if I have 5 data points, my x-axis should show (3, 6, 9, 12, 15). How do I get nvd3 to display all tick numbers? I pasted my code below for reference
var chart = nv.models.lineChart()
.options({
margin: {left: 100, bottom: 100},
x: function(d,i) { return i*3},
showXAxis: true,
showYAxis: true,
showLegend: true,
reduceXTicks: false,
showMaxMin: false,
//values: $scope.data.values.map( function(d,i) { return i*3; }),
useInteractiveGuideline: true,
transitionDuration: 2500,
showControls : true
})
;
chart.xAxis //Chart x-axis settings
.axisLabel('Ager')
.orient('bottom')
//.tickValues( function(d,i) { return i*3;})
.tickFormat(d3.format(',r'));
chart.yAxis //Chart y-axis settings
.axisLabel('Voltage (v)')
.tickFormat(d3.format('.02f')); nv.utils.windowResize(chart.update);
I've tried everything I can think of and read online to get nvd3 show all ticks in multiples of 3. Please help me out of this tricky situation.
Thanks in advance!

You could have read the d3 docs and see that .tickValues does not accept a function.
Construct the array of tick values based on the domain of the x-axis. Because the domain is not yet set you have to construct it yourself based on the data.
Using the SinCos example from the nvd3 site
var myData = sinAndCos();
var xExtent = d3.extent(myData[0].values, d=>d.x);
xExtent = [Math.floor(xExtent[0]), Math.ceil(xExtent[1])+1];
var xTicks = d3.range(xExtent[0], xExtent[1]).filter(n => n%3===0);
chart.xAxis
.axisLabel('Time (ms)')
.tickValues(xTicks)
.tickFormat(d3.format(',r'));
Complete example. It will not run directly from the browser (will not load nvd3 inside an iframe(??)). Copy it to a local file and run it from there.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link href="https://nvd3.org/assets/css/nv.d3.css" rel="stylesheet"/>
<script src="https://nvd3.org/assets/lib/d3.v3.js"></script>
<script src="https://nvd3.org/assets/js/nv.d3.js"></script>
</head>
<body>
<div id="chart">
<svg style="width:800px;height:500px;"></svg>
</div>
<script>
/*These lines are all chart setup. Pick and choose which chart features you want to utilize. */
nv.addGraph(function() {
var chart = nv.models.lineChart()
.margin({left: 100}) //Adjust chart margins to give the x-axis some breathing room.
.useInteractiveGuideline(true) //We want nice looking tooltips and a guideline!
.transitionDuration(350) //how fast do you want the lines to transition?
.showLegend(true) //Show the legend, allowing users to turn on/off line series.
.showYAxis(true) //Show the y-axis
.showXAxis(true) //Show the x-axis
;
var myData = sinAndCos();
var xExtent = d3.extent(myData[0].values, d=>d.x);
xExtent = [Math.floor(xExtent[0]), Math.ceil(xExtent[1])+1];
var xTicks = d3.range(xExtent[0], xExtent[1]).filter(n => n%3===0);
chart.xAxis //Chart x-axis settings
.axisLabel('Time (ms)')
.tickValues(xTicks)
.tickFormat(d3.format(',r'));
chart.yAxis //Chart y-axis settings
.axisLabel('Voltage (v)')
.tickFormat(d3.format('.02f'));
d3.select('#chart svg') //Select the <svg> element you want to render the chart in.
.datum(myData) //Populate the <svg> element with chart data...
.call(chart); //Finally, render the chart!
//Update the chart when window resizes.
nv.utils.windowResize(function() { chart.update() });
return chart;
});
/**************************************
* Simple test data generator
*/
function sinAndCos() {
var sin = [],sin2 = [],
cos = [];
//Data is represented as an array of {x,y} pairs.
for (var i = 0; i < 100; i++) {
sin.push({x: i, y: Math.sin(i/10)});
sin2.push({x: i, y: Math.sin(i/10) *0.25 + 0.5});
cos.push({x: i, y: .5 * Math.cos(i/10)});
}
//Line chart data should be sent as an array of series objects.
return [
{
values: sin, //values - represents the array of {x,y} data points
key: 'Sine Wave', //key - the name of the series.
color: '#ff7f0e' //color - optional: choose your own line color.
},
{
values: cos,
key: 'Cosine Wave',
color: '#2ca02c'
},
{
values: sin2,
key: 'Another sine wave',
color: '#7777ff',
area: true //area - set to true if you want this line to turn into a filled area chart.
}
];
}
</script>
</body>
</html>

Related

Dc.js Boxplot not creating outlines

Why is dc.js boxplot not creating any outlines? I am just created a simplified code based on http://dc-js.github.io/dc.js/examples/boxplot-basic.html
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<body>
<div id = 'boxch1'><br></div>
<script src="https://unpkg.com/crossfilter2#1.4.7/crossfilter.min.js"></script>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="http://unpkg.com/dc#3/dc.js"></script>
<script>
let exp = [
{"Expt":1, "Speed":8},
{"Expt":1, "Speed":7},
{"Expt":1, "Speed":9},
{"Expt":1, "Speed":1},
{"Expt":2, "Speed":8},
{"Expt":2, "Speed":6},
{"Expt":2, "Speed":8}];
dc.config.defaultColors(d3.schemeSet1);
var ndx = crossfilter(exp)
runDimension = ndx.dimension(function(d) {return +d.Run;});
runGroup = runDimension.group();
experimentDimension = ndx.dimension(function(d) {return "exp-" + d.Expt;});
speedArrayGroup = experimentDimension.group().reduce(
function(p,v) {
// keep array sorted for efficiency
p.splice(d3.bisectLeft(p, v.Speed), 0, v.Speed);
return p;
},
function(p,v) {
p.splice(d3.bisectLeft(p, v.Speed), 1);
return p;
},
function() {
return [];
}
);
var bp01 = dc.boxPlot("#boxch1");
bp01
.width(768)
.height(480)
.margins({top: 10, right: 50, bottom: 30, left: 50})
.dimension(experimentDimension)
.group(speedArrayGroup)
.elasticY(true)
.elasticX(true);
bp01.render()
</script>
</body>
</html>
I am not getting the box outlines as in the chart drawn below.
https://imgur.com/a/ELH5xlX
Thanks for including a complete example.
These kinds of problems are usually because you are missing dc.css.
In dc.js, and D3 code in general, any static attributes of SVG elements that are not controlled by data can be specified in either JS code or in CSS. This includes axis lines, outlines, fonts, etc.
Generally it makes customization easier to use classnames and leave the static attributes to CSS. But you do need to include dc.css.

How to capture the selection in a dc.js + crossfilter + d3.js chart?

perhaps the answer is very obvious and has nothing to do the libraries but with general javascript, JQuery or Ajax. I am very new to javascript and I was trying to implement a dashboard using flask as the backend.
Crossfilter and dc help me select ranges on the charts and see how that affects the whole dataset. If I add a:
<span class="filter"></span>
It will display the range above the chart
But that is a class "filter" inside a span object and not a variable or data that I can get inside the code. Below is what I use to display the chart (btw, the reset button does not appear at all)
<div class='span6' id='dc-close-chart'>
<h4>
close
</h4>
<p>range:
<span class="filter">
<a class="reset" href="javascript:closeChart.filterAll();dc.redrawAll();" style="display: none;">
reset
</a>
</span>
</p>
</div>
I would like to be able to do the following:
Be able to access that range and store it is a variable so I can access it and maybe post it using a submit button.
Be able to replace that label for an input textbox to modify the range and change the filter accordingly.
I've been looking around the crossfilter and dc.js forums but I didn't find anything relevant, what I want to do, is it even possible?
Below the JS code, can I create a variable that captures that?
var closeChart = dc.barChart("#dc-close-chart");
// set constants
var n_bins = 35;
d3.csv("/static/data2.csv", function (data) {
console.log(data);
data.forEach(function (d) {
d.close = d3.round(+d.close, 1);
});
// Run the data through crossfilter and load our 'facts'
var facts = crossfilter(data);
var all = facts.groupAll();
// count all the facts
dc.dataCount(".dc-data-count")
.dimension(facts)
.group(all);
// for Each chart numeric
var closeValue = facts.dimension(function (d) {
return d.close; // add the magnitude dimension
});
var closeValueGroupSum = closeValue.group()
.reduceSum(function (d) {
return d.close;
}); // sums
var closeValueGroupCount = closeValue.group()
.reduceCount(function (d) {
return d.close;
}) // counts
// extent
var closeExtent = d3.extent(data, function (d) {
return d.close;
});
// binwidth
var closebinWidth = (closeExtent[1] - closeExtent[0]) / n_bins;
//group
var closeGroup = closeValue.group(function (d) {
return Math.floor(d / closebinWidth) * closebinWidth;
});
// Setup the charts
// Magnitide Bar Graph Counted
closeChart.width(480)
.height(150)
.margins({
top: 10,
right: 10,
bottom: 20,
left: 40
})
.dimension(closeValue)
.group(closeGroup)
.transitionDuration(500)
.centerBar(true)
.gap(1) // 65 = norm
// .filter([3, 5])
.x(d3.scale.linear().domain(closeExtent).range([0, n_bins]))
.elasticY(true)
.xUnits(function () {
return n_bins;
})
.controlsUseVisibility(true)
.colors(['LimeGreen'])
.xAxis().tickFormat(function (v) {
return v;
});
// Render the Charts
dc.renderAll();
});
You can read the currently active filters using chart.filter() or chart.filters().
There isn't anything built in to parse filters from text, but if you figure out how to do that, you could apply the filter with
chart.replaceFilter([dc.filters.RangedFilter(min, max)])
RangedFilter docs.
replaceFilter docs.

How to handle No Data in pie chart?

I am currently working with pie charts in amCharts plugin. Sometimes I had to face no data in pie chart. In this scenario, amCharts loads no graph.
How can I handle no data in pie chart? Is there any method to display inactive pie chart (disabled pie chart or something)?
You can use AmCharts.addInitHandler function to set custom function to call before chart is drawn. You can use it to check if dataProvider is empty and make all kinds of modifications to the chart.
I.e.:
/**
* amCharts Plugin: handle empty pie chart
*/
AmCharts.addInitHandler(function(chart) {
// check if data is mepty
if (chart.dataProvider === undefined || chart.dataProvider.length === 0) {
// add some bogus data
var dp = {};
dp[chart.titleField] = "";
dp[chart.valueField] = 1;
chart.dataProvider.push(dp)
var dp = {};
dp[chart.titleField] = "";
dp[chart.valueField] = 1;
chart.dataProvider.push(dp)
var dp = {};
dp[chart.titleField] = "";
dp[chart.valueField] = 1;
chart.dataProvider.push(dp)
// disable slice labels and balloons
chart.labelsEnabled = false;
chart.balloonText = "";
// add label to let users know the chart is empty
chart.addLabel("50%", "50%", "The chart contains no data", "middle", 15);
// dim the whole chart
chart.alpha = 0.3;
}
}, ["pie"]);
var chart = AmCharts.makeChart("chartdiv", {
"type": "pie",
"theme": "light",
"dataProvider": [],
"valueField": "value",
"titleField": "title"
});
<script src="http://www.amcharts.com/lib/3/amcharts.js"></script>
<script src="http://www.amcharts.com/lib/3/pie.js"></script>
<script src="http://www.amcharts.com/lib/3/themes/light.js"></script>
<div id="chartdiv" style="width: 100%; height: 400px;"></div>

NVD3 x axis time scale misaligned

Im trying to set up a line chart nvd3 graphic, but im getting time value on x axis not vertically aligned, heres the code:
function fillData() {
var test1 = [],
test2 = [],
test3 = [];
var now = new Date(),
day = 1000*60*60*24;
var cont = 0;
for (var i = now - 9*day; i < now; i+=day)
{
var arr = [400,431,401,430,429,450,448,498,421,421];
var arr1 = [420,415,421,410,439,430,468,448,441,421];
var arr2 = [410,425,431,420,459,420,458,438,451,421];
test1.push({x: i, y: arr[cont]});
test2.push({x: i, y: arr1[cont]});
test3.push({x: i, y: arr2[cont]});
cont+=1;
} // fin for
return [
{
values: test1,
area: true,
key: 'test1',
color: '#81BA63'
},
{
values: test2,
area: true,
key: 'test2',
color: '#EAEAEA'
},
{
values: test3,
area: true,
key: 'test3',
color: '#6389BA'
}
];
}
nv.addGraph(function() {
var chart = nv.models.lineChart()
.margin({top: 0, bottom: 25, left: 45, right: 0})
.showLegend(true)
.forceY([300,500])
chart.yAxis
.showMaxMin(true)
.tickFormat(d3.format('.02'))
chart.xAxis
.showMaxMin(false)
.tickFormat(function(d) { return d3.time.format('%d - %b')(new Date(d)) });
chart.xScale(d3.time.scale());
d3.select('#sources-chart-line svg')
.datum(fillData())
.transition().duration(500)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
problem screenshot: http://oi57.tinypic.com/i6gq2t.jpg
Thanks in Advance!!
The problem is that the number of data points (9) and axis ticks (8) is different. D3 picks "representative" ticks for the scale, which aren't necessarily aligned with the data points. Therefore, you get ticks between data points for which the date is still correct, but not at exactly midnight like the data points.
One way of fixing this is to explicitly specify the tick values:
var data = fillData();
chart.xAxis
.tickValues(data[0].values.map(function(d) { return d.x; }));
This is a bit ugly, but it shows the principle and you can refactor the code to make these values better accessible.

how to disable the x axis and y axis line in google api line chart

im using google api for line graph in my web application. in that line chart i dont want x axis line and y axis line, but i cant to fine how to remove the lines except the graph. could you please help me. i used this example for my practice
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Year', 'Sales', 'Expenses'],
['2004', 1000, 400],
['2005', 1170, 460],
['2006', 660, 1120],
['2007', 1030, 540]
]);
var options = {
title: 'Company Performance'
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
you cant remove or disable your x and y axis in google api the alter way is to set the baselineColor and gridlineColor same as the background color and set the textPosition to none.
vAxis:{
baselineColor: '#fff',
gridlineColor: '#fff',
textPosition: 'none'
}
With the current version of Google Charts, the following removes axis lines:
hAxis: {
baselineColor: 'none',
ticks: []
},
vAxis: {
baselineColor: 'none',
ticks: []
}

Resources