2016-10-10 6 views
2

Я искал все онлайн, но я не могу найти то, что ищу. Я думаю, может быть, я не использую правильную терминологию.Как фильтровать данные с помощью D3.js?

У меня есть простая диаграмма рассеяния в D3.js. Мой файл csv похож:

Group, X, Y 

1, 4.5, 8 
1, 9, 12 
1, 2, 19 
2, 9, 20 
3, 2, 1 
3, 8, 2 

Я хочу фильтровать по группам. Таким образом, график будет отображаться по умолчанию только значения группы 1, но вы можете также выбрать, чтобы увидеть значение 2-й группы или групп 3.

Вот код, у меня есть уже ...

var margin = {top: 20, right: 20, bottom: 30, left: 40}, 
    width = 960 - margin.left - margin.right, 
    height = 500 - margin.top - margin.bottom; 

var x = d3.scale.linear() 
    .range([0, width]); 

var y = d3.scale.linear() 
    .range([height, 0]); 

var svg = 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 + ")"); 

d3.csv("l2data.csv", function(error, data) { 
    if (error) throw error; 

    // Coerce the strings to numbers. 
    data.forEach(function(d) { 
    d.x = +d.x; 
    d.y = +d.y; 
    }); 

    // Compute the scales’ domains. 
    x.domain(d3.extent(data, function(d) { return d.x; })).nice(); 
    y.domain(d3.extent(data, function(d) { return d.y; })).nice(); 

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

    // Add the y-axis. 
    svg.append("g") 
     .attr("class", "y axis") 
     .call(d3.svg.axis().scale(y).orient("left")); 

    // Add the points! 
    svg.selectAll(".point") 
     .data(data) 
    .enter().append("path") 
     .attr("class", "point") 
     .attr("d", d3.svg.symbol().type("triangle-up")) 
     .attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; }); 
}); 

ответ

1

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

Вам необходимо создать переменную для хранения созданных точек после создания, затем использовать список выбора или что-то еще, чтобы скрыть или показать точки на основе выбора.

// this variable will hold your created symbols 
 
var points, 
 
    margin = {top: 20, right: 20, bottom: 30, left: 40}, 
 
    width = 400 - margin.left - margin.right, 
 
    height = 300 - margin.top - margin.bottom; 
 

 
var x = d3.scale.linear() 
 
.range([0, width]); 
 

 
var y = d3.scale.linear() 
 
.range([height, 0]); 
 

 
var select = d3.select('body') 
 
    .append('div') 
 
    .append('select') 
 
    .on('change', function(){ 
 
     // get selected group 
 
     var group = select.property('value'); 
 
     // hide those points based on the selected value. 
 
     points.style('opacity', function(d){ 
 
     return d.group == group ? 1:0; 
 
     }); 
 
    }); 
 

 
var svg = 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 data = [ 
 
     {group:1, x:4.5, y:8}, 
 
     {group:1, x:9, y:12}, 
 
     {group:1, x:2, y:19}, 
 
     {group:2, x:9, y:20}, 
 
     {group:3, x:2, y:1}, 
 
     {group:3, x:8, y:2} 
 
    ]; 
 

 
// Coerce the strings to numbers. 
 
data.forEach(function(d) { 
 
    d.x = +d.x; 
 
    d.y = +d.y; 
 
}); 
 

 
var groups = d3.set(data.map(function(d){ return d.group; })).values(); 
 

 
// create group filtering select list 
 
select.selectAll('option') 
 
    .data(groups) 
 
    .enter().append('option').text(function(d){ return d }); 
 

 
select.property('value', groups[0]); // default selected group 
 

 

 
// Compute the scales’ domains. 
 
x.domain(d3.extent(data, function(d) { return d.x; })).nice(); 
 
y.domain(d3.extent(data, function(d) { return d.y; })).nice(); 
 

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

 
// Add the y-axis. 
 
svg.append("g") 
 
    .attr("class", "y axis") 
 
    .call(d3.svg.axis().scale(y).orient("left")); 
 

 
// Add the points! 
 
points = svg.selectAll(".point") 
 
    .data(data) 
 
    .enter().append("path") 
 
    .attr("class", "point") 
 
    .attr("d", d3.svg.symbol().type("triangle-up")) 
 
    .attr("transform", function(d){ 
 
     return "translate("+x(d.x)+","+y(d.y)+")"; 
 
    }) 
 
    // hide all points expect default group 
 
    .style('opacity', function(d){ return d.group == groups[0]?1:0; });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.3.13/d3.min.js"></script>

+0

Спасибо @PierreB! Это было очень полезно. Я изучал все выходные и не смог понять это. Я ценю время, которое вы мне помогли. –

+0

Добро пожаловать :-) – PierreB

3

У вас есть хороший старт здесь! Чтобы сделать это еще лучше, вам нужно три вещи. Компонент пользовательского интерфейса для выбора группы, прослушиватель событий для обнаружения изменения этого компонента и функция обработки обновления для визуализации.

В добавленном коде я создал три новые функции для каждой части жизненного цикла d3. Введите дескрипторы добавления новых элементов в наш график. Обновление обновляет существующие значения на основе изменения связанных данных. Exit удаляет любые элементы, которые больше не привязаны к ним. Прочитайте классическую статью https://bost.ocks.org/mike/join/ от Майка Бостока по этой ссылке, чтобы получить дополнительную информацию. При этом у вас есть возможность добавлять прохладные переходы на ваш график, а также настраивать способ ввода и выхода данных.

var data = [{ group: 1, x: 5.5, y: 0 }, { group: 1, x: 0, y: 6 }, { group: 1, x: 7.5, y: 8 }, { group: 2, x: 4.5, y: 4 }, { group: 2, x: 4.5, y: 2 }, { group: 3, x: 4, y: 4 }]; 
 

 
var margin = {top: 20, right: 20, bottom: 30, left: 40}, 
 
    width = 960 - margin.left - margin.right, 
 
    height = 500 - margin.top - margin.bottom; 
 

 
var x = d3.scale.linear() 
 
    .range([0, width]); 
 

 
var y = d3.scale.linear() 
 
    .range([height, 0]); 
 
    
 

 
var svg = 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 + ")"); 
 

 
    
 
// Coerce the strings to numbers. 
 
data.forEach(function(d) { 
 
    d.x = +d.x; 
 
    d.y = +d.y; 
 
}); 
 

 
// Compute the scales’ domains. 
 
x.domain(d3.extent(data, function(d) { return d.x; })).nice(); 
 
y.domain(d3.extent(data, function(d) { return d.y; })).nice(); 
 

 

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

 
// Add the y-axis. 
 
svg.append("g") 
 
    .attr("class", "y axis") 
 
    .call(d3.svg.axis().scale(y).orient("left")); 
 

 
// Get a subset of the data based on the group 
 
function getFilteredData(data, group) { 
 
\t return data.filter(function(point) { return point.group === parseInt(group); }); 
 
} 
 

 
// Helper function to add new points to our data 
 
function enterPoints(data) { 
 
    // Add the points! 
 
    svg.selectAll(".point") 
 
    .data(data) 
 
    .enter().append("path") 
 
    .attr("class", "point") 
 
    .attr('fill', 'red') 
 
    .attr("d", d3.svg.symbol().type("triangle-up")) 
 
    .attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; }); 
 
} 
 

 
function exitPoints(data) { 
 
    svg.selectAll(".point") 
 
     .data(data) 
 
     .exit() 
 
     .remove(); 
 
} 
 

 
function updatePoints(data) { 
 
    svg.selectAll(".point") 
 
     .data(data) 
 
     .transition() 
 
\t .attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; }); 
 
} 
 

 
// New select element for allowing the user to select a group! 
 
var $groupSelector = document.querySelector('.group-select'); 
 
var groupData = getFilteredData(data, $groupSelector.value); 
 

 
// Enter initial points filtered by default select value set in HTML 
 
enterPoints(groupData); 
 

 
$groupSelector.onchange = function(e) { 
 
    var group = e.target.value; 
 
    var groupData = getFilteredData(data, group); 
 

 
    updatePoints(groupData); 
 
    enterPoints(groupData); 
 
    exitPoints(groupData); 
 

 
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 
<label> 
 
    Group 
 
    <select class="group-select"> 
 
    <option value=1 selected>1</option> 
 
    <option value=2>2</option> 
 
    <option value=3>3</option> 
 
    </select> 
 
</label>

Смежные вопросы