如何在d3.js中使用crossfilter进行分组和过滤

时间:2015-07-20 16:56:12

标签: javascript d3.js crossfilter

js用户,

我刚开始使用d3.js& crossfilter并试图利用Adam Pearce在meteor map上的例子来可视化天气数据。由于我热衷于分析多年来的天气变化,我有多年的记录,而不是在“名称”列中只有一个记录。以下是原始数据和我自己的数据的示例:

原始数据

name mass_g year cartodb_id ....

Vilna 1 1967 34039

Silistra 1 1917 34017

我的数据

名称降雨年份cartodb_id ....

station_A 100 1997 34039

station_A 200 1998 34039

station_B 300 1997 34017

station_B 400 1998 34017

我不确定哪里出错,因为它没有产生任何错误。然而,

  1. crossfilter似乎没有在地图上生效
  2. 它没有按照地图上的电台对降雨量值进行分组(我认为它们相互重叠)
  3. 我无法对这两个条形图进行分组,这样我就可以显示多年来的降雨时间序列,以及降雨分布(我认为需要使用一些Reduce函数,但我无法弄清楚)
  4. 下面是我的js脚本来替换原来的drawMap.js(对不起,它有点太长了;谢谢你提出任何建议!):

    var width = 1000,
        height = 500;
    
    var proj = d3.geo.mercator()
            .center([103.8,1.33])
            .scale(100000)
            .rotate([0,0]);
    
    var path = d3.geo.path()
            .projection(proj);
    
    // for map
    var zoom = d3.behavior.zoom()
        .translate(proj.translate())
        .scale(proj.scale())
        .scaleExtent([100000,Infinity]) //.scaleExtent([height*.33, 4 * height])
        .on("zoom", zoom);
    
    
    var svg = d3.select("#map").append("svg")
            .attr("width", width)
            .attr("height", height)
            .call(zoom);
    
    function zoom() {
        proj.translate(d3.event.translate).scale(d3.event.scale);
        svg.selectAll("path").attr("d", path);
        circles
            .attr("cx", function(d){return proj([d.long, d.lat])[0];})
            .attr("cy", function(d){return proj([d.long, d.lat])[1];});
    }
    
    var borders = svg.append("g");
    
    var impacts = svg.append("g");
    
    // colours and scales for the corresponding values in map
    
    var metorScale = d3.scale.pow().exponent(.5).domain([0, 100, 1000, 2000, 3000, 5000, 8000]);
    
    var colorScale = d3.scale.linear().domain([1980, 1888, 1996, 2004, 2014]);
    
    var tooltip = d3.select("body").append("div")
        .attr("class", "tooltip")
        .style("opacity", 1e-6)
        .style("background", "rgba(250,250,250,.7)");
    
    tooltip.append("img")
        .attr("id", "tooltipImg")
        .attr("height", 200)
        .attr("width", 200)
        .style("opacity", "1");
    
    // change the fell file to our rainfall
    // file has to be at aggregated level for each year
    // one station one value for one year
    // change the json file to our map
    queue()
        .defer(d3.json, "Planning_Area_Census2010_WGS84.json") 
        .defer(d3.csv, "yearlyrainfall.csv")
        /*.defer(d3.json, "pics.json")*/
        .await(ready);
    
    var metors;
    
    // for the rest of the code
    // removed pics in the inputs
    function ready(error, topology, csv){
        borders.selectAll("path")
            .data(topojson.object(topology, topology.objects.Planning_Area_Census2010_WGS84)
                    .geometries)
        .enter()
            .append("path")
            .attr("d", path)
            .attr("class", "border")
    
        rawMetors = csv;
    
    
      // change mass_g to rainfall
      // cartodb_id is a key for our station
    
        metors = [];
        rawMetors.forEach(function(d){
            d.rainfall = +d.rainfall;
            d.year = +d.year;
            d.id = +d.cartodb_id;
            d.name = d.name;
            d.region = d.region;
            metors.push(d);  
    
        });
        metors.sort(function(a, b){return a.id - b.id;})
    
      // size tag to rainfall
      //colour tag to year
        metorScale
            .range([1.5, 2, 3, 4, 5, 8, 10]);
    
        colorScale
            .range(["#FFFF66", "#FFFF00", "#E68000", "#D94000", "#CC0000"]);
    
        circles = impacts.selectAll("circle")
            .data(metors).enter()
                .append("svg:a")
                    .attr("xlink:href", function(d) { return d.database; })
                    .attr("xlink:show", "new")
                .append("circle")
                    .attr("cx", function(d){return proj([d.long, d.lat])[0];})
                    .attr("cy", function(d){return proj([d.long, d.lat])[1];})
                    .attr("r",  function(d){return metorScale(d.rainfall);})
                    .attr("id", function(d){return "id" + d.id;})
                    .style("fill", function(d){return colorScale(d.year);   })
            .on("mouseover", function(d){
                d3.select(this)
                    .attr("stroke", "black")
                    .attr("stroke-width", 1)
                    .attr("fill-opacity", 1);
    
                tooltip
                    .style("left", (d3.event.pageX + 5) + "px")
                    .style("top", (d3.event.pageY - 5) + "px")
                    .transition().duration(300)
                    .style("opacity", 1)
                    .style("display", "block")
    
                updateDetails(d);
                })
            .on("mouseout", function(d){
                d3.select(this)
                    .attr("stroke", "")
                    .attr("fill-opacity", function(d){return 1;})
    
                tooltip.transition().duration(700).style("opacity", 0);
            });
    
    
        metorsCF = crossfilter(metors),
            all = metorsCF.groupAll(),
    
            year = metorsCF.dimension(function(d){return d.year;}), /*creating a type dimension*/
            years = year.group(function(d){return Math.floor(d);}),
    
            rainfall = metorsCF.dimension(function(d){return d.rainfall }), /*creating a type dimension*/
            rainfalls = rainfall.group(function(d){return Math.floor(d/10)*10;}),   
    
        // for grouping at var charts
    
        // group by type, change to region  
          region = metorsCF.dimension(function(d){return d.region;}), /*creating a type dimension*/
          regions = region.group();
    
        // create group of ids
             cartoDbId = metorsCF.dimension(function(d){return d.id;}); /*creating a type dimension*/
             cartoDbIds = cartoDbId.group()
    
    
    
    
      // create all the bar charts
    
      // first one draw by group of years
    
        // change the domain relate to the format tick in barchart.js
        var charts = [
            barChart()
                    .dimension(year)
                    .group(years)
                .x(d3.scale.linear()
                    .domain([1970,2020])
                    .rangeRound([-1, 20*24-5])),
    
        // change the domain relate to the format tickvalues in barchart.js
            barChart()
                    .dimension(rainfall)
                    .group(rainfalls)
                .x(d3.scale.linear()
                    .domain([1,10000])
                    .rangeRound([0,20*24]))
        ];
    
        var chart = d3.selectAll(".chart")
                .data(charts)
                .each(function(chart){chart.on("brush", renderAll).on("brushend", renderAll)});
    
        d3.selectAll("#total")
                .text(metorsCF.size());
    
    
        function render(method){
            d3.select(this).call(method);
        }
    
    
        lastFilterArray = [];
        metors.forEach(function(d, i){
            lastFilterArray[i] = 1;
        });
    
        function renderAll(){
            chart.each(render);
    
            var filterArray = cartoDbIds.all();
            filterArray.forEach(function(d, i){
                if (d.value != lastFilterArray[i]){
                    lastFilterArray[i] = d.value;
                    d3.select("#id" + d.key).transition().duration(500)
                            .attr("r", d.value == 1 ? 2*metorScale(metors[i].rainfall) : 0)
                        .transition().delay(550).duration(500)
                            .attr("r", d.value == 1 ? metorScale(metors[i].rainfall) : 0);
    
                }
            })
    
            d3.select("#active").text(all.value());
        }
    
        window.reset = function(i){
            charts[i].filter(null);
            renderAll();
        }
    
        renderAll();
    }
    
    
    // to show the labels on what to display on map
     var printDetails = [
                        {'var': 'name', 'print': 'Station'},
                        {'var': 'region', 'print': 'Region'},
                        {'var': 'rainfall', 'print': 'Rainfall(mm)'},
                        {'var': 'year', 'print': 'Year'}];
    
    
    
    
    function updateDetails(metorsCF){
    //  var image = new Image();
    //  image.onload = function(){
    //      document.getElementById("tooltipImg").src = 'pictures/' + metor.cartodb_id + '.jpg';}
    //  image.src = 'pictures/' + metor.cartodb_id + '.jpg';
    
        tooltip.selectAll("div").remove();
        tooltip.selectAll("div").data(printDetails).enter() 
            .append("div")
                .append('span')
                    .text(function(d){return d.print + ": ";})              
                    .attr("class", "boldDetail")
                .insert('span')
                    .text(function(d){return metorsCF[d.var];})
                    .attr("class", "normalDetail");
    }
    
      [1]: http://roadtolarissa.com/meteors/
    

0 个答案:

没有答案