D3.js通过刷牙聚焦+上下文

时间:2014-10-29 03:21:57

标签: d3.js

我试图通过使用Twitter数据分析刷新来学习d3.js焦点+上下文。我试图根据给出的数据生成时间序列图,但它没有按照预期的那样出现。我创造了小提琴。有人可以看看它,并给我一个关于我如何解决这个问题的建议?

var margin = {top: 10, right: 10, bottom: 100, left: 40},
        margin2 = { top: 430, right: 10, bottom: 20, left: 40},
        width = 960 - margin.left - margin.right,
        height = 500 - margin.top - margin.bottom,
        height2 = 500 - margin2.top - margin2.bottom;

    var parseDate = d3.time.format("%Y-%m-%d %I:%M:%S").parse;

    var x = d3.time.scale().range([0, width]),
        x2 = d3.time.scale().range([0, width]),
        y = d3.scale.linear().range([height, 0]),
        y2 = d3.scale.linear().range([height2, 0]);

    var xAxis = d3.svg.axis().scale(x).orient("bottom"),
        xAxis2 = d3.svg.axis().scale(x2).orient("bottom"),
        yAxis = d3.svg.axis().scale(y).orient("left");

    var brush = d3.svg.brush()
        .x(x2)
        .on("brush", brushed);

    var area = d3.svg.area()
        .interpolate("monotone")
        .x(function(d) { return x(d.date); })
        .y0(height)
        .y1(function(d) { return y(d.count); });

    var area2 = d3.svg.area()
        .interpolate("monotone")
        .x(function(d) { return x2(d.date); })
        .y0(height2)
        .y1(function(d) { return y2(d.count); });

    var svg = d3.select(".trend-graph").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom);

    svg.append("defs").append("clipPath")
        .attr("id","clip")
        .append("rect")
        .attr("width", width)
        .attr("height", height);

    var focus = svg.append("g")
        .attr("class", "focus")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var context = svg.append("g")
        .attr("class", "context")
        .attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");

    d3.csv("/TwitterProject/slides/results.csv", type, function(error, data){

        x.domain(d3.extent(data.map(function(d) { return d.date; })));
        y.domain([0, d3.max(data.map(function(d) { return d.count; }))])
        x2.domain(x.domain());
        y2.domain(y.domain());

        focus.append("path")
            .datum(data)
            .attr("class", "area")
            .attr("d", area);

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

        focus.append("g")
            .attr("class","y axis")
            .call(yAxis);

        context.append("path")
            .datum(data)
            .attr("class","area")
            .attr("d", area2);

        context.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height2 + ")")
            .call(xAxis2);

        context.append("g")
            .attr("class", "x brush")
            .call(brush)
        .selectAll("rect")
            .attr("y", -6)
            .attr("height", height2 + 7);

    });

    function brushed(){

        x.domain(brush.empty() ? x2.domain() : brush.extent());
        focus.select(".area").attr("d", area);
        focus.select(".x.axis").call(xAxis);
    }

    function type(d) {
        d.date = parseDate(d.date);
        d.count = +d.count;     
        return d;
    }

JSFiddle

此外,y轴显示错误。我认为问题在于计算"计数"每分钟,但我无法弄清楚如何解决这个问题。

情节应该是这样的。

enter image description here

编辑:

我所做的改变:

var bins = {};

x.domain(d3.extent(data.map(function(d) { return d.date; })));
//y.domain([0, d3.max(data.map(function(d) { return d.count; }))]).
y.domain([0, bins]).range([height, 0]);
x2.domain(x.domain());
y2.domain(y.domain()).range([height2, 0]);

function type(d) {
    d.date = parseDate(d.date);
    d.count = +d.count;     
    var key = d.date.toDateString();
    bins[key] = bins[key] || 0;
    bins[key] += d.count;
    console.log(bins);
    return d;
}

1 个答案:

答案 0 :(得分:1)

您的数据分辨率为1秒,因此您将获得非常嘈杂的图形(实际上正是您正在获得的图形)。您可能希望进行一些分箱,在这些分箱中汇总数据以减少噪音。

原则上,代码看起来像这样(按分钟聚合):

function type(d) {
    d.date = parseDate(d.date);
    d.count = +d.count;
    d.date.setSeconds(0);
    var key = df(d.date);          
    bins[key] = bins[key] || 0;
    bins[key] += d.count;
    return d;
}

然后在d3.csv内:

var binData = d3.entries(bins);
    binData.forEach(function(d) { d.key = parseDate(d.key); });
    binData.sort(function(a,b) { return b.key - a.key; });

由于Date个对象不能作为关联数组键发挥作用,因此还有一些额外的瑕疵。现在,key中包含value(日期)和binData的元素,可用于创建图表。

完整演示here