d3:仅仅接近足够的点进行线性内插 [英] d3: linearly interpolate only close-enough points

查看:205
本文介绍了d3:仅仅接近足够的点进行线性内插的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个具有相应日期的值数组, [{date:d1,value:v1},...,{date:dn,value:vn}] ,我想使用d3.js可视化。只要随后的测量在一定的时间范围内,例如不超过一周,我对测量之间的d3内插感到满意。



然而,当随后记录离得更远,我不想要d3连接它们。

解决方案

你的问题不完全清楚:interpolate



如果您为x轴使用时间刻度,D3会自动为您连接这些点,并创建一条线(SVG path 元素),而不考虑数据点中的时间间隔。但是有一种方法可以在该行中制作空白:使用 line.defined() 。根据API:


如果指定了defined,则将定义的访问器设置为指定的函数或布尔值并返回此行生成器。问题是,为了这种方法工作,你必须设置一个给定的值(比方说, null ),在您不想绘制线条的日期之间(也就是说,不够近的日期你的问题)。



这是一个工作演示:在我的数据集中,我的数据从7月10日跳到17月10月(超过1周)。所以,我只是创建一个 null 值在这两者之间的任何日期(在我的演示,16-Oct)。然后,在行生成器中,行跳转 null 值,使用定义

  d3.line()。define(function(d){return d.value!= null;})

结果是该行从10月10日到10月17日跳跃:



var data = [{date:1-Oct-16,value:14},{date:2-Oct-16 ,值:33},{date:3-Oct-16,value:12},{date:4-Oct-16,value:43},{date:5-Oct-16 :54},{date:6-Oct-16,value:71},{date:7-Oct-16,value:32},{date:16-Oct-16 },{date:17-Oct-16,value:54},{date:18-Oct-16,value:14} {date:20-Oct-16,value:32},{date:21-Oct-16,value:56},{date:22-Oct-16,value:24} :23-Oct-16,value:42},{date:24-Oct-16,value:52},{date:25-Oct-16,value:66} 26-Oct-16,value:34},{date:27-Oct-16,value:62},{date:28-Oct-16,value:48} Oct-16,value:51},{date:30-Oct-16,value:42}]; var parseDate = d3.timeParse(%d-%b-%y); data.forEach函数(d){d.date = parseDate(d.date);}); var svg = d3.select(body).append(svg).attr(width,500)高度,200); var xScale = d3.scaleTime()。range([20,480]); var yScale = d3.scaleLinear()。range([180,10]); xScale.domain(d3.extent {return d.date;}); yScale.domain([0,d3.max(data,function(d){return d.value;})]); var xAxis = d3.axisBottom(xScale).tickFormat d3.timeFormat(%d)); var yAxis = d3.axisLeft(yScale); var baseline = d3.line().defined(function(d){return d.value!= null;}).x function(d){return xScale(d.date);}).y(function(d){return yScale(d.value);}); svg.append(path)//添加valueline path..attr(d,baseline(data))attr(fill,none)attr(stroke,teal); svg.append(g).attr(transform,translate(0,180)).call(xAxis); svg.append(g)。attr ).attr(class,y axis).call(yAxis);

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


Suppose I have an array of values with corresponding dates, [{date: d1, value: v1}, ..., {date: dn, value: vn}], that I'd like to visualize using d3.js. As long as subsequent measurements are within a certain time range, for example not more than a week apart, I am happy with d3 interpolating between the measurements.

However, when subsequent records are farther apart, I don't want d3 to connect them. What would be the easiest way to achieve this?

解决方案

Your question is not exactly clear: by "interpolate", I believe you mean "connecting the dots".

If you use a time scale for your x axis, D3 will automatically connect the dots for you and create a line (an SVG path element), regardless the time separation in the data points. But there is a way for making "gaps" in that line: using line.defined(). According to the API:

If defined is specified, sets the defined accessor to the specified function or boolean and returns this line generator.

The problem is, for this approach to work, you'll have to set a given value (let's say, null) in your dataset, between the dates in which you don't want to draw the line (that is, the dates that are not close enough, as you say in your question). You can do this manually or using a function.

This is a working demo: in my dataset, my data jumps from 7-Oct to 17-Oct (more than 1 week). So, I just created a null value in any date between these two (in my demo, 16-Oct). Then, in the line generator, the line jumps this null value, using defined:

d3.line().defined(function(d){return d.value != null;})

The result is that the line jumps from 7-Oct to 17-Oct:

var data = [{date: "1-Oct-16",value: 14},
{date: "2-Oct-16",value: 33},
{date: "3-Oct-16",value: 12},
{date: "4-Oct-16",value: 43},
{date: "5-Oct-16",value: 54},
{date: "6-Oct-16",value: 71},
{date: "7-Oct-16",value: 32},
{date: "16-Oct-16",value: null},
{date: "17-Oct-16",value: 54},
{date: "18-Oct-16",value: 14},
{date: "19-Oct-16",value: 34},
{date: "20-Oct-16",value: 32},
{date: "21-Oct-16",value: 56},
{date: "22-Oct-16",value: 24},
{date: "23-Oct-16",value: 42},
{date: "24-Oct-16",value: 52},
{date: "25-Oct-16",value: 66},
{date: "26-Oct-16",value: 34},
{date: "27-Oct-16",value: 62},
{date: "28-Oct-16",value: 48},
{date: "29-Oct-16",value: 51},
{date: "30-Oct-16",value: 42}];

var parseDate = d3.timeParse("%d-%b-%y");

data.forEach(function (d) {
    d.date = parseDate(d.date);
});

var svg = d3.select("body")
    .append("svg")
    .attr("width", 500)
    .attr("height", 200);
		
var xScale = d3.scaleTime().range([20, 480]);
var yScale = d3.scaleLinear().range([180, 10]);

xScale.domain(d3.extent(data, function (d) {
    return d.date;
    }));
yScale.domain([0, d3.max(data, function (d) {
    return d.value;
    })]);

var xAxis = d3.axisBottom(xScale).tickFormat(d3.timeFormat("%d"));

var yAxis = d3.axisLeft(yScale);

var baseline = d3.line()
	  .defined(function(d){return d.value != null;})
    .x(function (d) {
      return xScale(d.date);
    })
    .y(function (d) {
      return yScale(d.value);
    });
		
svg.append("path") // Add the valueline path.
.attr("d", baseline(data))
.attr("fill", "none")
.attr("stroke", "teal");

svg.append("g")
    .attr("transform", "translate(0,180)")
    .call(xAxis);

svg.append("g")
.attr("transform", "translate(20,0)")
.attr("class", "y axis")
    .call(yAxis);

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

这篇关于d3:仅仅接近足够的点进行线性内插的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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