title: Limit number of Y axis ticks by keeping a top tick above the bar in d3
body: <p>In my d3 bar chart, I should have a top Y-axis tick (with horizontal grid line) above the tallest bar if it goes above the last tick. This is achieved by calculating the last tick, then applied using <code>tickValues()</code>. </p>
  
  <p>Also there should be maximum 5 ticks and grid lines including the x-axis domain (0). I have tried this using <code>ticks()</code> but it is not working with <code>tickValues()</code>. Any solution for this? </p>
  
  <pre><code>// container size
  var margin = {top: 10, right: 10, bottom: 30, left: 30},
  width = 400,
  height = 300;
  
  var data = [
  {"month":"DEC","setup":{"count":26,"id":1,"label":"Set Up","year":"2016","graphType":"setup"}},
  {"month":"JAN","setup":{"count":30,"id":1,"label":"Set Up","year":"2017","graphType":"setup"}},
  {"month":"FEB","setup":{"count":30,"id":1,"label":"Set Up","year":"2017","graphType":"setup"}}];
  
  var name = 'dashboard';
  
  // x scale
  var xScale = d3.scale.ordinal()
  .rangeRoundBands([0, width], 0.2);
  
  // set x and y scales
  xScale.domain(data.map(function(d) { return d.month; }));
  
  // x axis
  var xAxis = d3.svg.axis()
  .scale(xScale)
  .orient('bottom')
  .outerTickSize(0);
  
  var yScale = d3.scale.linear()
  .domain([0, d3.max(data, function(d) {  
      return d.setup.count;
  })])
  .range([height, 0]);
  
  var ticks = yScale.ticks(),
  lastTick = ticks[ticks.length-1];    
  var newLastTick = lastTick + (ticks[1] - ticks[0]);  
  if (lastTick &lt; yScale.domain()[1]){
      ticks.push(lastTick + (ticks[1] - ticks[0]));
  }
  
  // adjust domain for further value
  yScale.domain([yScale.domain()[0], newLastTick]);
  
  // y axis
  var yAxis = d3.svg.axis()
  .scale(yScale)
  .orient('left')
  .tickSize(-width, 0, 0) 
  .tickFormat(d3.format('d'))
  .tickValues(ticks);
  
  
  // create svg container
  var svg = d3.select('#chart')
  .append('svg')
  .attr('class','d3-setup-barchart')
  .attr('width', width + margin.left + margin.right)
  .attr('height', height + margin.top + margin.bottom)
  .append('g')
  .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  //.on('mouseout', tip.hide);        
  
  // apply tooltip
  //svg.call(tip);
  
  // Horizontal grid (y axis gridline)
  svg.append('g')         
  .attr('class', 'grid horizontal')
  .call(d3.svg.axis()
        .scale(yScale)
        .orient('left')
        .tickSize(-width, 0, 0) 
        .tickFormat('')
        .tickValues(ticks)
        );
  
  // create bars
  var bars = svg.selectAll('.bar')
  .data(data)
  .enter()
  .append('g');
  
  bars.append('rect')
  .attr('class', function(d,i) {
      return 'bar';
  })
  .attr('id', function(d, i) {
      return name+'-bar-'+i;
  })
  .attr('x', function(d) { return xScale(d.month); })
  .attr('width', xScale.rangeBand())
  .attr('y', function(d) { return yScale(d.setup.count); })
  .attr('height', function(d) { return height - yScale(d.setup.count); })
  .on('click', function(d, i) {
      d3.select(this.nextSibling)
      .classed('label-text selected', true);
      d3.select(this)
      .classed('bar selected', true);  
      d3.select('#'+name+'-axis-text-'+i)
      .classed('axis-text selected', true);
  });
  //.on('mouseover', tip.show)
  //.on('mouseout', tip.hide);
  
  // apply text at the top
  bars.append('text')
  .attr('class',function(d,i) {
      return 'label-text';
  })
  .attr('x', function(d) { return xScale(d.month) + (xScale.rangeBand()/2) - 10; })
  .attr('y', function(d) { return yScale(d.setup.count) + 2 ; })
  .attr('transform', function() { return 'translate(10, -10)'; })
  .text(function(d) { return d.setup.count; });
  
  // draw x axis
  svg.append('g')
  .attr('id', name+'-x-axis')
  .attr('class', 'x axis')
  .attr('transform', 'translate(0,' + height + ')')
  .call(xAxis);
  
  // apply class &amp; id to x-axis texts
  d3.select('#'+name+'-x-axis')
  .selectAll('text')
  .attr('class', function(d,i) {
      return 'axis-text';
  })
  .attr('id', function(d,i) { return name+'-axis-text-' + i; });
  
  // draw y axis
  svg.append('g')
  .attr('class', 'y axis')
  .call(yAxis)
  .append('text')
  .attr('transform', 'rotate(-90)')
  .attr('y', 6)
  .attr('dy', '.71em')
  .style('text-anchor', 'end');
  
  // remove 0 in y axis
  svg.select('.y')
  .selectAll('.tick')
  .filter(function (d) { 
      return d === 0 || d % 1 !== 0;     
  }).remove();
  
  svg
  .select('.horizontal')
  .selectAll('.tick')
  .filter(function (d) { 
      return d === 0 || d % 1 !== 0;     
  }).remove();
  </code></pre>
  
  <p><a href="https://jsfiddle.net/betasquirrel/1wf1jts6/2/" rel="nofollow noreferrer"><strong>JSFiddle</strong></a></p>