如何在鼠标悬停时获取直方图中数据元素的索引? [英] How to get the index of the data element in a histogram on mouseover?

查看:59
本文介绍了如何在鼠标悬停时获取直方图中数据元素的索引?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 d3.v3.min.js 直方图,将其用作参考使用d3的直方图,我想在一个单独的图(散点图)中突出显示落在该直方图的一个条形内的所有点.为此,我挂钩了矩形的mouseover事件,以在一个bin中获取值.效果很好,但是我无法从原始输入数组中获取它们的索引:

I have a d3.v3.min.js histogram created using this as reference Histogram chart using d3 and I'd like to highlight in a separate plot (scatter plot) all the points that fall within one bar of this histogram. To this end I hook on the mouseover event of the rectangle to get the values within one bin. This works fine but I can't get their indices from the original input array:

var data = d3.layout.histogram().bins(xTicks)(values);

bar.append("rect")
   .attr("x", 1)
   .attr("width", (x(data[0].dx) - x(0)) - 1)
   .attr("height", function(d) { return height - y(d.y); })
   .attr("fill", function(d) { return colorScale(d.y) })
   .on("mouseover", function (d, i) { console.log(d); });

d是一个数组,其中包含bin中的所有值,而i是bin索引.我需要传递给histogram函数的原始数据值的索引,以便可以在另一个图中按索引查找它们(而不是对该值进行二进制搜索).

d is an array containing all the values within the bin, and i is the bin index. I need the indices of the original data values I passed to the histogram function so that I can look them up in the other plot by index (as opposed to a binary search needed on the value).

推荐答案

您不仅可以将数字值传递给直方图生成器,还可以创建带有附加信息的对象数组:

Instead of just passing number values to the histogram generator you could create an array of objects carrying additional information:

// Generate a 1000 data points using normal distribution with mean=20, deviation=5
var f = d3.random.normal(20, 5);

// Create full-fledged objects instead of mere numbers.
var values = d3.range(1000).map(id => ({
                                  id: id,
                                  value: f()
}));

// Accessor function for the objects' value property.
var valFn = d => d.value;

// Generate a histogram using twenty uniformly-spaced bins.
var data = d3.layout.histogram()
  .bins(x.ticks(20))
  .value(valFn)      // Provide accessor function for histogram generation
  (values);

通过提供直方图生成器的访问器功能,然后您就可以从该对象数组中创建垃圾箱.因此,调用直方图生成器将导致垃圾箱中充满对象,而不仅仅是原始数字.然后,您可以在事件处理程序中通过引用访问数据对象.这些对象将携带所有初始信息,例如本例中的id属性,索引或您放置在它们中的其他任何内容.

By providing an accessor function to the histogram generator you are then able to create the bins from this array of objects. Calling the histogram generator will consequently result in bins filled with objects instead of just raw numbers. In an event handler you are then able to access your data objects by reference. The objects will carry all the initial information, be it the id property as in my example, an index or anything else you put in them in the first place.

查看下面的代码片段以进行演示:

Have a look at the following snippet for a working demo:

var color = "steelblue"; 
var f = d3.random.normal(20, 5);
// Generate a 1000 data points using normal distribution with mean=20, deviation=5
var values = d3.range(1000).map(id => ({
                                id: id,
                                value: f()
}));
var valFn = d => d.value;

// A formatter for counts.
var formatCount = d3.format(",.0f");

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

var max = d3.max(values, valFn);
var min = d3.min(values, valFn);
var x = d3.scale.linear()
      .domain([min, max])
      .range([0, width]); 

// Generate a histogram using twenty uniformly-spaced bins.
var data = d3.layout.histogram()
    .bins(x.ticks(20))
    .value(valFn)
    (values);

var yMax = d3.max(data, function(d){return d.length});
var yMin = d3.min(data, function(d){return d.length});
var colorScale = d3.scale.linear()
            .domain([yMin, yMax])
            .range([d3.rgb(color).brighter(), d3.rgb(color).darker()]);

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

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

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 + ")");

var bar = svg.selectAll(".bar")
    .data(data)
  .enter().append("g")
    .attr("class", "bar")
    .attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; })
    .on("mouseover", d => { console.log(d)});

bar.append("rect")
    .attr("x", 1)
    .attr("width", (x(data[0].dx) - x(0)) - 1)
    .attr("height", function(d) { return height - y(d.y); })
    .attr("fill", function(d) { return colorScale(d.y) });

bar.append("text")
    .attr("dy", ".75em")
    .attr("y", -12)
    .attr("x", (x(data[0].dx) - x(0)) / 2)
    .attr("text-anchor", "middle")
    .text(function(d) { return formatCount(d.y); });

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

/*
* Adding refresh method to reload new data
*/
function refresh(values){
  // var values = d3.range(1000).map(d3.random.normal(20, 5));
  var data = d3.layout.histogram()
    .value(valFn)
    .bins(x.ticks(20))
    (values);

  // Reset y domain using new data
  var yMax = d3.max(data, function(d){return d.length});
  var yMin = d3.min(data, function(d){return d.length});
  y.domain([0, yMax]);
  var colorScale = d3.scale.linear()
              .domain([yMin, yMax])
              .range([d3.rgb(color).brighter(), d3.rgb(color).darker()]);

  var bar = svg.selectAll(".bar").data(data);

  // Remove object with data
  bar.exit().remove();

  bar.transition()
    .duration(1000)
    .attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; });

  bar.select("rect")
      .transition()
      .duration(1000)
      .attr("height", function(d) { return height - y(d.y); })
      .attr("fill", function(d) { return colorScale(d.y) });

  bar.select("text")
      .transition()
      .duration(1000)
      .text(function(d) { return formatCount(d.y); });

}

// Calling refresh repeatedly.
setInterval(function() {
  var values = d3.range(1000).map(id => ({
                                  id: id,
                                  value: f()
  }));
  refresh(values);
}, 2000);

body {
  font: 10px sans-serif;
}

.bar rect {
  shape-rendering: crispEdges;
}

.bar text {
  fill: #999999;
}

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

.as-console-wrapper {
  height: 20%;
}

<script src="https://d3js.org/d3.v3.min.js"></script>

这篇关于如何在鼠标悬停时获取直方图中数据元素的索引?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆