Чтение tsv файла с фильтром

Я пытаюсь построить простую гистограмму из файла tsv и буду признателен за помощь.

Прежде всего, вот пример входного файла:

ind  count      
0    1228

1    0

2    238

3    9

Мне нужно построить график количества записей (ось Y) по сравнению с «количеством» (ось X).

У пользователя есть возможность через HTML-страницу решить, при каком значении «счетчика» скрывать данные. Например, подавить все записи, где count=0. Изменение количества записей и тем самым диапазона данных влияет на шкалы обеих осей.

У меня нет проблем с получением всех данных и настройкой шкал для осей. Я делаю это в качестве первого шага сразу после чтения данных из файла (d3.tsv...). Но как мне это сделать, если я хочу использовать только частичные данные входного файла? я использую

d3.max(data, function(d){ return +d.indx}

чтобы получить количество записей в моем входном файле.

Я немного поиграл с методом filter(), но (помимо того, что пока безуспешно) я все еще думаю, что правильное место для фильтрации данных было бы сразу - при чтении входного файла.

Скорее всего, это настолько очевидно, что ответ заставит меня покраснеть, но мой мозг сдался. На этом спасибо за ответ!

А теперь немного моего кода:

function drawBarGraph( minCountNum){
    d3.tsv("../../data/test.tsv", function( error, data){               //get the number of rows and the largest number of the "total" column for scaling purposes

    //y-axis: use number of lines in input file
    var bar_num = d3.max(data, function(d) {  return +d.indx;} );                   //use plus sign (+) in front of a variable to ensure conversion to a numeric value. 
    //x-axis: use largest value of "total reads" from input file;           
    var data_max = d3.max(data, function(d) {  return +d.total;} );
    //set up canvas size 
    var margin = { top: 30, right: 20, bottom: 40, left: 50},
        width = 800 - margin.left - margin.right,                   
        height = 2 * bar_num + 2;                                                   //each bar is 1px high and spaced by 1px; add 2px to the bottom to allow a little space between the xAxis and the first data point

    var bar_height = 1;         //yes, draw the bars 1px high                                                   

    //set up the x and y scales
    var xScale = d3.scale.linear()
                .domain([0, data_max])      //define original range with min and max 
                .range([0, width]);         //define what resulting range should be 
    var yScale = d3.scale.linear()
                .domain([0, bar_num*2])         
                .range([0, height]);        

    //set up the x and y axes 
    var xAxis = d3.svg.axis()
                .scale( xScale)
                .orient("bottom")
                //.ticks( 5);               //let d3 decide on the number of ticks used or calculate based on longest x-value 
    var yAxis = d3.svg.axis()
                .scale( yScale)
                .orient("left")
                .ticks( 0);                 //no ticks or make them the index or node id's

    var canvas = d3.select("body")
                .append("svg")
                    .attr("width", width + margin.left + margin.right)      
                    .attr("height", height + margin.top + margin.bottom)    
                .append("g")                
                    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");  

    var div = d3.select("body").append("div")
                .attr("class", "tooltip")   //add the CSS tooltip
                .style("opacity", 0);

    canvas.selectAll("rect")                
                .data(data)
                .enter()                    
                //.filter(function(d) { return +d.total > 0; })  //this returns 'undefined'
                    .append("svg:a")
                        .attr("xlink:show", "new")
                            .attr("xlink:href", function(d){return ncbi_url + d.taxon_id;})
                    .append("rect")         
                    .attr("width", function(d) { return xScale(d.total);})  
                    .attr("height", bar_height)     
                    .attr("y", function(d,i){ return i * (bar_height + 1);})  
                    .attr("fill", function(d) { return d.color;})
                    .on("mouseover", function(d){
                        div.transition()
                            .duration(200)
                            .style("opacity", .9);
                        div.html(
                                "Node ID: " + d.id + "<br/>Tot. Reads: " + d.total)
                            .style("left", (d3.event.pageX) + "px")
                            .style("top", (d3.event.pageY - 28) + "px");
                    })
                    .on("mouseout", function(d){
                        div.transition()
                            .duration(500)
                            .style("opacity", 0);
                    });

    canvas.append("g")                                              
                    .attr("transform", "translate(0," + height + ")")
                    .call(xAxis);

    canvas.append("text")   //add the x-axis label 
                    .attr("x", (width / 2))
                    .attr("y", height + margin.bottom)          
                    .style("text-anchor", "middle")
                    .text("Total Reads");

    canvas.append("g")                                              
                    .call(yAxis);

    canvas.append("text")   //add the y-axis label 
                    .attr("transform", "rotate(-90)")
                    .attr("y", 0 - margin.left + 20)            
                    .attr("x", 0 - (height / 2))
                    .attr("dy", "1em")
                    .style("text-anchor", "middle")
                    .text("Node #");

    canvas.append("text")  //add a title
                    .attr("x", (width / 2))
                    .attr("y", 0 - (margin.top / 2))
                    .attr("text-anchor", "middle")
                    .style("font-size", "20px")
                    .style("text-decoration", "underline")
                    .text("Node Plot");
})   

}

person user2544265    schedule 02.07.2013    source источник


Ответы (1)


Да, лучший способ сделать это — сразу после получения данных убедиться, что все последующие операции учитывают только то подмножество, которое вам нужно. Для этого можно использовать функцию .filter().

var threshold = ...;
var newdata = data.filter(function(d) { return +d.total > threshold; });

(Я выбрал total в качестве поля для фильтрации, как в опубликованном вами коде).

person Lars Kotthoff    schedule 03.07.2013
comment
Спасибо, Ларс! По какой-то причине я думал, что метод фильтра работает только после того, как я использовал методы select/selectAll в своем наборе данных. У меня было всего 10 дней с D3, и я решил, что моя проблема довольно проста. Спасибо, что нашли время! - person user2544265; 03.07.2013
comment
На самом деле это две разные функции фильтрации: та, о которой вы говорите, реализована в D3 для выбора, а та, которую я использовал, является общей вещью Javascript. Хотя оба делают одно и то же. - person Lars Kotthoff; 03.07.2013