Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Counting the number of continuous blue bars till the hover bar

I need to count the blue bars' longest streak till the bar we are hovering over for the bar diagram obtained by code below:enter image description here

For e.g. If I hover on first bar (which is red ) the Longest streak should show 0, second hover ( which is also red ) also 0. When hovered on third bar that is blue it should show 1. and until we hover around bar number 18 it should show Longest Streak as 2 . From 20 onward where there are more than two consecutive blues bars it say 3. Even if I hover on bar # 21 it should still show Longest streak as 3. and it should keep showing that until four or more number of blue bars appear consecutively.

body {
  font: 10px sans-serif;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

.bar {
  fill: orange;
}

.bar:hover {
  fill: cyan ;
}

.x.axis path {
  display: none;
}

    .grid .tick {
        stroke: lightgrey;
        opacity: 0.7;
    }

    .grid path {
        stroke-width: 0;
    }

.d3-tip {
  line-height: 1;
  font-weight: bold;
  padding: 12px;
  background: rgba(0, 0, 0, 0.8);
  color: cyan;
  border-radius: 2px;
}

/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
  box-sizing: border-box;
  display: inline;
  font-size: 10px;
  width: 100%;
  line-height: 1;
  color: rgba(0, 0, 0, 0.8);
  content: "\25BC";
  position: absolute;
  text-align: center;
}

/* Style northward tooltips differently */
.d3-tip.n:after {
  margin: -1px 0 0 0;
  top: 100%;
  left: 0;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
<script>

var margin = {top: 40, right: 20, bottom: 50, left: 70},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var formatPercent = d3.format(".0%");

var x = d3.scale.ordinal()
    .rangeRoundBands([0, width], .5);

var y = d3.scale.linear()
    .range([height, 0]);

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");
    //.tickFormat(formatPercent);


var tip = d3.tip()
  .attr('class', 'd3-tip')
  .offset([-10, 0])
  .html(function(d) {
      return "<strong>Time Used:</strong> <span style='color:cyan'>" + d.frequency + "</span>" + "<br/>" + "<strong>Longest Streak:</strong> <span>" + (d.criteria.match(/lightblue/g) || []).length+"</span>";
  })

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

svg.call(tip);

function make_y_axis() {
    return d3.svg.axis()
        .scale(y)
        .orient("left")
        .ticks(10)
}
d3.tsv("pass_fail_bars_data.tsv", type, function (error, data) {
  x.domain(data.map(function(d) { return d.problem_number; }));
  y.domain([0, d3.max(data, function(d) { return d.frequency; })]);

  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
    .append("text")
      .attr("transform", "rotate(-90)")
      .attr("x", -height / 3)
     .attr("y", -50)
     .attr("dy", ".71em")
     .style("text-anchor", "end")
      .text("Time Used (Seconds)");
  svg.append("g")
  .attr("class", "grid")
  .call(make_y_axis()
      .tickSize(-width, 0, 0)
      .tickFormat("")
  )

  svg.append("g")
  .attr("class", "x axis")
  .attr("transform", "translate(0," + height + ")")
  .call(xAxis)
 .append("text")
 .attr("transform", "rotate(0)")
 .attr("x", width / 2)
  .attr("y", 40)
 .attr("dx", "1em")
 .style("text-anchor", "middle")
 .text("Problem #")
 .attr("fill", "blue");



  svg.selectAll(".bar")
      .data(data)
    .enter().append("rect")
      .attr("class", "bar")
      .attr("x", function (d) { return x(d.problem_number); })
      .attr("width", x.rangeBand())
      .attr("y", function(d) { return y(d.frequency); })
      .attr("height", function (d) { return height - y(d.frequency); })
      .style("fill", function(d) { return d.criteria; })
      .on('mouseover', tip.show)
      .on('mouseout', tip.hide)

});

function type(d) {
  d.frequency = +d.frequency;
  return d;
}

</script>

Currently it shows only the current blue bar count. That is if I hover on blue bar it is counting that bar only and displaying longest streak as 1. Which in this case true but When I hover on bar # 20, then also it is displaying "longest Streak" as 1 when it should display as 3.

Any suggestion How can I modify this code further to get the desired result?

Here is the data I am using "pass_fail_bars_data.tsv"

problem_number  frequency   criteria    
1   08167   "red"
2   01492   "red"
3   02780   "lightblue"
4   04253   "red"
5   12702   "red"
6   02288   "lightblue"
7   02022   "red"
8   06094   "red"
9   06973   "lightblue"
10  00153   "lightblue"
11  00747   "red"
12  04025   "red"
13  02517   "lightblue"
14  06749   "red"
15  07507   "lightblue"
16  01929   "red"
17  00098   "red"
18  05987   "lightblue"
19  06333   "lightblue"
20  09056   "lightblue"
21  02758   "red"
22  01037   "lightblue"
23  02465   "lightblue"
24  00150   "red"
25  01971   "lightblue"
26  00074   "lightblue"
like image 885
Artiga Avatar asked Jan 04 '16 09:01

Artiga


1 Answers

You can do this by making a small for loop to calculate the streak and set that in the data.

Something like this:

d3.tsv("my.tsv", type, function (error, data) {
  var count = 0;

  var longestStreak = 0;
  data.forEach(function(d){
    if (d.criteria  == "lightblue"){
      count++;
    } else {
      count  = 0;//reset the count
    }
    if (count > longestStreak){
      longestStreak = count;//set the new streak.
    }

    d.streak = longestStreak;
  });

Then In the tip function you can return the streak instead of calculating it.

var tip = d3.tip()
  .attr('class', 'd3-tip')
  .offset([-10, 0])
  .html(function(d) {
      console.log(d)
      return "<strong>Time Used:</strong> <span style='color:cyan'>" + d.frequency + "</span>" + "<br/>" + "<strong>Longest Streak:</strong> <span>" + d.streak+"</span>";
  })

Working code here

Hope this helps!

like image 188
Cyril Cherian Avatar answered Sep 30 '22 10:09

Cyril Cherian