应用过滤器功能以选择D3.js中的CSV多行

时间:2019-04-02 10:18:59

标签: javascript csv parsing d3.js filter

我有一个具有以下格式的数据表:

    Month,KPI,Type,Unit,S40401,S40402,S40403
    JAN,A,Units FTP,PC,2000,4000,6000
    JAN,B,Invoice Sales FTP,EUR,2000,4000,6000
    JAN,C,Gross Sales Actual FTP,EUR,2000,4000,6000
    JAN,D,Net Sales FTP,EUR,2000,4000,6000
    JAN,E,CMC FTP,EUR,2000,4000,6000
    FEB,A,Units FTP,PC,2000,4000,6000
    FEB,B,Invoice Sales FTP,EUR,2000,4000,6000
    FEB,C,Gross Sales Actual FTP,EUR,2000,4000,6000
    FEB,D,Net Sales FTP,EUR,2000,4000,6000
    FEB,E,CMC FTP,EUR,2000,4000,6000

...
...
...

如果该数据仅包含一个变量/ KPI(例如A-E中的一个),则将数据解析为D3-Chart根本没有问题。但是由于我要选择特定的行,因此变得很复杂。我无法适应CSV文件,数据必须在此结构中。因此,我唯一的解决方案是按行过滤。

如何使用.filter()过滤数据以解析特定行? 例如:以仅来自“ A行”或“ B行”的方式过滤数据  列“ KPI”被选中了吗?

我认为导入CSV的代码的这一部分需要过滤器功能。我已经尝试过但没有成功:

<script>
var freqData;
d3.csv("export.csv", function(data) {
    data = csv.filter(function(row) {
        return row['KPI'] == 'C';
   freqData = data.map(function(d) { return {
        Month: d.Month, 
        freq: {
            S40401: +d.S40401,
            S40402: +d.S40402,
            S40403: +d.S40403
        }}
    });
  dashboard('#dashboard',freqData);
});

</script>

下面的整个代码:

<script>
function dashboard(id, fData){
    var barColor = 'steelblue';
    function segColor(c){ return {S40401:"#04B404",S40402:"#045FB4",S40403:"#B40404"}[c]; }

    // compute total for each state.
    fData.forEach(function(d){d.total=d.freq.S40401+d.freq.S40402+d.freq.S40403;});

    // function to handle histogram.
    function histoGram(fD){
        var hG={},    hGDim = {t: 60, r: 0, b: 30, l: 0};
        hGDim.w = 500 - hGDim.l - hGDim.r, 
        hGDim.h = 300 - hGDim.t - hGDim.b;

        //create svg for histogram.
        var hGsvg = d3.select(id).append("svg")
            .attr("width", hGDim.w + hGDim.l + hGDim.r)
            .attr("height", hGDim.h + hGDim.t + hGDim.b).append("g")
            .attr("transform", "translate(" + hGDim.l + "," + hGDim.t + ")");

        // create function for x-axis mapping.
        var x = d3.scale.ordinal().rangeRoundBands([0, hGDim.w], 0.1)
                .domain(fD.map(function(d) { return d[0]; }));

        // Add x-axis to the histogram svg.
        hGsvg.append("g").attr("class", "x axis")
            .attr("transform", "translate(0," + hGDim.h + ")")
            .call(d3.svg.axis().scale(x).orient("bottom"));

        // Create function for y-axis map.
        var y = d3.scale.linear().range([hGDim.h, 0])
                .domain([0, d3.max(fD, function(d) { return d[1]; })]);

        // Create bars for histogram to contain rectangles and freq labels.
        var bars = hGsvg.selectAll(".bar").data(fD).enter()
                .append("g").attr("class", "bar");

        //create the rectangles.
        bars.append("rect")
            .attr("x", function(d) { return x(d[0]); })
            .attr("y", function(d) { return y(d[1]); })
            .attr("width", x.rangeBand())
            .attr("height", function(d) { return hGDim.h - y(d[1]); })
            .attr('fill',barColor)
            .on("mouseover",mouseover)// mouseover is defined below.
            .on("mouseout",mouseout);// mouseout is defined below.

        //Create the frequency labels above the rectangles.
        bars.append("text").text(function(d){ return d3.format(".3f")(d[1])})
            .attr("x", function(d) { return x(d[0])+x.rangeBand()/2; })
            .attr("y", function(d) { return y(d[1])-5; })
            .attr("text-anchor", "middle");

        function mouseover(d){  // utility function to be called on mouseover.
            // filter for selected state.
            var st = fData.filter(function(s){ return s.Month == d[0];})[0],
                nD = d3.keys(st.freq).map(function(s){ return {type:s, freq:st.freq[s]};});

            // call update functions of pie-chart and legend.    
            pC.update(nD);
            leg.update(nD);
        }

        function mouseout(d){    // utility function to be called on mouseout.
            // reset the pie-chart and legend.    
            pC.update(tF);
            leg.update(tF);
        }

        // create function to update the bars. This will be used by pie-chart.
        hG.update = function(nD, color){
            // update the domain of the y-axis map to reflect change in frequencies.
            y.domain([0, d3.max(nD, function(d) { return d[1]; })]);

            // Attach the new data to the bars.
            var bars = hGsvg.selectAll(".bar").data(nD);

            // transition the height and color of rectangles.
            bars.select("rect").transition().duration(500)
                .attr("y", function(d) {return y(d[1]); })
                .attr("height", function(d) { return hGDim.h - y(d[1]); })
                .attr("fill", color);

            // transition the frequency labels location and change value.
            bars.select("text").transition().duration(500)
                .text(function(d){ return d3.format(".3f")(d[1])})
                .attr("y", function(d) {return y(d[1])-5; });            
        }        
        return hG;
    }

    // function to handle pieChart.
    function pieChart(pD){
        var pC ={},    pieDim ={w:250, h: 250};
        pieDim.r = Math.min(pieDim.w, pieDim.h) / 2;

        // create svg for pie chart.
        var piesvg = d3.select(id).append("svg")
            .attr("width", pieDim.w).attr("height", pieDim.h).append("g")
            .attr("transform", "translate("+pieDim.w/2+","+pieDim.h/2+")");

        // create function to draw the arcs of the pie slices.
        var arc = d3.svg.arc().outerRadius(pieDim.r - 10).innerRadius(0);

        // create a function to compute the pie slice angles.
        var pie = d3.layout.pie().sort(null).value(function(d) { return d.freq; });

        // Draw the pie slices.
        piesvg.selectAll("path").data(pie(pD)).enter().append("path").attr("d", arc)
            .each(function(d) { this._current = d; })
            .style("fill", function(d) { return segColor(d.data.type); })
            .on("mouseover",mouseover).on("mouseout",mouseout);

        // create function to update pie-chart. This will be used by histogram.
        pC.update = function(nD){
            piesvg.selectAll("path").data(pie(nD)).transition().duration(500)
                .attrTween("d", arcTween);
        }        
        // Utility function to be called on mouseover a pie slice.
        function mouseover(d){
            // call the update function of histogram with new data.
            hG.update(fData.map(function(v){ 
                return [v.Month,v.freq[d.data.type]];}),segColor(d.data.type));
        }
        //Utility function to be called on mouseout a pie slice.
        function mouseout(d){
            // call the update function of histogram with all data.
            hG.update(fData.map(function(v){
                return [v.Month,v.total];}), barColor);
        }
        // Animating the pie-slice requiring a custom function which specifies
        // how the intermediate paths should be drawn.
        function arcTween(a) {
            var i = d3.interpolate(this._current, a);
            this._current = i(0);
            return function(t) { return arc(i(t));    };
        }    
        return pC;
    }

    // function to handle legend.
    function legend(lD){
        var leg = {};

        // create table for legend.
        var legend = d3.select(id).append("table").attr('class','legend');

        // create one row per segment.
        var tr = legend.append("tbody").selectAll("tr").data(lD).enter().append("tr");

        // create the first column for each segment.
        tr.append("td").append("svg").attr("width", '16').attr("height", '16').append("rect")
            .attr("width", '16').attr("height", '16')
            .attr("fill",function(d){ return segColor(d.type); });

        // create the second column for each segment.
        tr.append("td").text(function(d){ return d.type;});

        // create the third column for each segment.
        tr.append("td").attr("class",'legendFreq')
            .text(function(d){ return d3.format(".3f")(d.freq);});

        // create the fourth column for each segment.
        tr.append("td").attr("class",'legendPerc')
            .text(function(d){ return getLegend(d,lD);});

        // Utility function to be used to update the legend.
        leg.update = function(nD){
            // update the data attached to the row elements.
            var l = legend.select("tbody").selectAll("tr").data(nD);

            // update the frequencies.
            l.select(".legendFreq").text(function(d){ return d3.format(".3f")(d.freq);});

            // update the percentage column.
            l.select(".legendPerc").text(function(d){ return getLegend(d,nD);});        
        }

        function getLegend(d,aD){ // Utility function to compute percentage.
            return d3.format("%")(d.freq/d3.sum(aD.map(function(v){ return v.freq; })));
        }

        return leg;
    }

    // calculate total frequency by segment for all state.
    var tF = ['S40401','S40402','S40403'].map(function(d){ 
        return {type:d, freq: d3.sum(fData.map(function(t){ return t.freq[d];}))}; 
    });    

    // calculate total frequency by state for all segment.
    var sF = fData.map(function(d){return [d.Month,d.total];});

    var hG = histoGram(sF), // create the histogram.
        pC = pieChart(tF), // create the pie-chart.
        leg= legend(tF);  // create the legend.
}
</script>

<script>
var freqData;
d3.csv("dataset_sales.csv", function(data) {
   freqData = data.map(function(d) { return {
        Month: d.Month, 
        freq: {
            S40401: +d.S40401,
            S40402: +d.S40402,
            S40403: +d.S40403
        }}
    });
  dashboard('#dashboard',freqData);
});


</script>

1 个答案:

答案 0 :(得分:0)

您没有关闭函数,也没有对数据进行过滤。
您将数据加载为data,然后在csv上运行了过滤功能。
以下应该可以满足您的需求

var freqData;
d3.csv("test.csv", function(data) {
    filteredData = data.filter(function(row) {
        return row['KPI'] == 'C';
    });
    freqData = filteredData.map(function(d) { 
        return {
            Month: d.Month, 
            freq: {
                S40401: +d.S40401,
                S40402: +d.S40402,
                S40403: +d.S40403
            }
        }
    });
    console.log("freqData", freqData);
});

输出:

[{
  "Month": "JAN",
  "freq": {
    "S40401": 2000,
    "S40402": 4000,
    "S40403": 6000
  }, {
  "Month": "FEB",
  "freq": {
    "S40401": 2000,
    "S40402": 4000,
    "S40403": 6000
  }
}]