D3 js BoxPlot已计算数据

时间:2017-04-07 15:08:11

标签: javascript d3.js

我需要制作一个D3 BoxPlot。 我有一个包含数十亿行的数据集,将原始数据发送到客户端是不可行的。所以,我创建了一个API,并且只发送了包含每列的max / min / std_dev值的汇总版本。

在所有示例中(one two)我看到使用D3 BoxPlot,数据摘要是在客户端完成的(与我的情况相反)。

是否可以将BoxPlot与已计算的数据一起使用?有人有例子吗?

2 个答案:

答案 0 :(得分:4)

好吧,既然你已经获得了已经计算过的数据,那么这里的任务就更容易了!

首先,让我们设定比例。在您comment中复制/粘贴的数据中,您有maxmin,我将用于第三和第一四分位数。由于您的数据中没有第二个四分位数(中位数),因此我会使用mean。此外,由于您的数据有3个相同的对象,我会稍微更改它,以使框不同。

所以,设置y比例:

var yScale = d3.scaleLinear()
    .domain([0, d3.max(data, function(d) {
        return d.max
    }) * 1.1])
    .range([h - padding, padding]);

这是标准的线性刻度。

对于x刻度,我使用带刻度:

var xScale = d3.scaleBand()
    .domain(data.map(function(d) {
        return d.label
    }))
    .range([padding, w - padding])
    .padding(0.4);

给我们矩形的左右限制是非常好的。

现在,只需要打印矩形和线条(中位数)。

对于矩形,请注意数学以将第三个四分位数作为矩形的顶部,并将第一个四分位数作为其高度(yheight属性):

var boxes = svg.selectAll("foo")
    .data(data)
    .enter()
    .append("rect")
    .attr("fill", "none")
    .attr("stroke", "black")
    .attr("x", function(d) {
        return xScale(d.label)
    })
    .attr("width", xScale.bandwidth())
    .attr("y", function(d) {
        return yScale(d.max)
    })
    .attr("height", function(d) {
        return yScale(d.min) - yScale(d.max)
    });

最后,对于这些行,我们只对meany1值使用y2

var lines = svg.selectAll("foo")
    .data(data)
    .enter()
    .append("line")
    .attr("stroke", "black")
    .attr("stroke-width", 4)
    .attr("x1", function(d) {
        return xScale(d.label)
    })
    .attr("x2", function(d) {
        return xScale(d.label) + xScale.bandwidth()
    })
    .attr("y1", function(d) {
        return yScale(d.mean)
    })
    .attr("y2", function(d) {
        return yScale(d.mean)
    })

以下是包含数据结构的演示:



var data = [{
  "count": "2",
  "min": "1.6",
  "max": "4.1",
  "label": "labelA",
  "stddev": "0.72",
  "mean": "3.1"
}, {
  "count": "2",
  "min": "1.1",
  "max": "2.9",
  "label": "labelB",
  "stddev": "0.72",
  "mean": "2.2"
}, {
  "count": "2",
  "min": "2.4",
  "max": "3.6",
  "label": "labelC",
  "stddev": "0.72",
  "mean": "2.7"
}];

var w = 500,
  h = 200,
  padding = 30,
  padding2 = 20;

var svg = d3.select("body")
  .append("svg")
  .attr("width", w)
  .attr("height", h);

var yScale = d3.scaleLinear()
  .domain([0, d3.max(data, function(d) {
    return d.max
  }) * 1.1])
  .range([h - padding2, 10]);

var xScale = d3.scaleBand()
  .domain(data.map(function(d) {
    return d.label
  }))
  .range([padding, w - padding])
  .padding(0.4);

var xAxis = d3.axisBottom(xScale);
var yAxis = d3.axisLeft(yScale);

var gX = svg.append("g")
  .attr("transform", "translate(0," + (h - padding2) + ")")
  .call(xAxis);

var gY = svg.append("g")
  .attr("transform", "translate(" + padding + ",0)")
  .call(yAxis);

var boxes = svg.selectAll("foo")
  .data(data)
  .enter()
  .append("rect")
  .attr("fill", "none")
  .attr("stroke", "black")
  .attr("x", function(d) {
    return xScale(d.label)
  })
  .attr("width", xScale.bandwidth())
  .attr("y", function(d) {
    return yScale(d.max)
  })
  .attr("height", function(d) {
    return yScale(d.min) - yScale(d.max)
  });

var lines = svg.selectAll("foo")
  .data(data)
  .enter()
  .append("line")
  .attr("stroke", "black")
  .attr("stroke-width", 4)
  .attr("x1", function(d) {
    return xScale(d.label)
  })
  .attr("x2", function(d) {
    return xScale(d.label) + xScale.bandwidth()
  })
  .attr("y1", function(d) {
    return yScale(d.mean)
  })
  .attr("y2", function(d) {
    return yScale(d.mean)
  })

<script src="https://d3js.org/d3.v4.min.js"></script>
&#13;
&#13;
&#13;

PS:获得胡须的数据后,您可以按照相同的原则简单地添加用于创建此基本结构的行的代码。

答案 1 :(得分:1)

您可以在d3fc中找到boxplot渲染组件:

https://d3fc.io/api/series-api.html#boxplot

您可以使用此功能呈现已经汇总的数据

(完全披露:我是d3fc的作者之一)