2016-08-21 2 views
5
структуру

данных:d3.js: Доступ к данным вложенным 2 уровень вниз

var data = [ 
    {name: "male", 
    values: [ 
    { count: 12345, 
     date: Date 2015-xxx, 
     name: "male" }, 
    {...} 
    ] 
    }, 
    {name: "female", 
    values: [ 
    { count: 6789, 
     date: Date 2015-xxx, 
     name: "female" }, 
    {...} 
    ] 
    } 
] 

Значения, которые я хочу получить доступ к данным являются [а] .values ​​[б] .Count

используются значения рисовать круги для моего участка

код окружности участка:

focus.selectAll(".dot") 
    .data(data) 
    .enter().append("circle") 
    .attr("class", "dot") 
    .attr("cx", function(d,i) { return x(d.values[i].date); }) 
    .attr("cy", function(d,i) { return y(d.values[i].count); }) 
    .attr("r", 4) 
    .style("fill", function(d,i) { return color(d.values[i].name); }) 

проблема заключается в том, что i = 1 becaus е его позиции в объекте.

Что я хочу сделать, это пропустить все objects под номером values. Как я могу это сделать?

Редактировать: Я хочу узнать, как это сделать, не изменяя данные, чтобы улучшить свои навыки.

Спасибо.

ответ

4

Самый простой способ - использовать lib как underscore.js для редактирования массива данных.

От подчеркивания Документов:

сплющить _.flatten (массив, [неглубокий]) Спрямлять вложенный массив (вложенность может быть любой глубине). Если вы пройдете неглубоко,> массив будет только сплющен на один уровень.

_.flatten([1, [2], [3, [[4]]]]); 
-> [1, 2, 3, 4]; 

_.flatten([1, [2], [3, [[4]]]], true); 
-> [1, 2, 3, [[4]]]; 

карту _.map (список, iteratee, [контекст]) Псевдоним: сбор Создает новый массив значений путем отображения каждого значения в списке через функцию преобразования> (iteratee). Итератору передаются три аргумента: значение>, затем индекс (или ключ) итерации и, наконец, ссылка на список> whole.

_.map([1, 2, 3], function(num){ return num * 3; }); 
=> [3, 6, 9] 
_.map({one: 1, two: 2, three: 3}, function(num, key){ return num * 3; }); 
=> [3, 6, 9] 
_.map([[1, 2], [3, 4]], _.first); 
=> [1, 3] 

Underscore documentation

В своем коде вы можете сделать что-то подобное:

var flatData = _.flatten(_.map(data, (d)=>d.values)); 
focus.selectAll(".dot") 
    .data(data) 
    .enter().append("circle") 
    .attr("class", "dot") 
    .attr("cx", function(d,i) { return x(d.date); }) 
    .attr("cy", function(d,i) { return y(d.count); }) 
    .attr("r", 4) 
.style("fill", function(d,i) { return color(d.name); }) 
+2

спасибо, это работает, но это можно сделать только с чистым JS или d3 без изменения данных ? Я хочу улучшить свои навыки :) – Shawn

+0

@shawn Конечно, вы можете. Underscore.js является открытым исходным кодом, вы можете проверить, как это делается. Это не так сложно понять. Код здесь: http://underscorejs.org/underscore.js Вы не можете легко сделать это с помощью d3 без изменения данных ... Существует способ, но он не оптимизирован. Вы quand делаете данные foreach, затем делаете focus.selectAll по значениям и добавляете круги таким образом. – rm4

1

Есть несколько способов сделать то, что вы хотите использовать только D3, без каких-либо других библиотек и без изменяя данные. Один из них использует groups для обработки «более высоких» уровней данных (относительно вложенных данных). Давайте посмотрим его в этом коде:

Во-первых, я издевался до набора данных, как ваша:

var data = [ 
    {name: "male", 
    values: [{ x: 123,y: 234}, 
     { x: 432,y: 221}, 
     { x: 199,y: 56}] 
    }, 
    {name: "female", 
    values: [{ x: 223,y: 111}, 
     { x: 67,y: 288}, 
     { x: 19, y: 387}] 
    } 
]; 

Это данные, которые мы собираемся использовать.Я собираюсь сделать график рассеяния здесь (как пример), так, давайте установим домены для весов доступа второго уровня данных (x и y внутри values):

var xScale = d3.scaleLinear().range([20, 380]) 
    .domain([0, d3.max(data, function(d){ 
     return d3.max(d.values, function(d){ 
      return d.x; 
     }) 
})]); 

var yScale = d3.scaleLinear().range([20, 380]) 
    .domain([0, d3.max(data, function(d){ 
     return d3.max(d.values, function(d){ 
      return d.y; 
     }) 
})]); 

Теперь самый важная часть: мы будем привязки данных к «группам», а не к окружности элементов:

var circlesGroups = svg.selectAll(".circlesGroups") 
    .data(data) 
    .enter() 
    .append("g") 
    .attr("fill", function(d){ return (d.name == "male") ? "blue" : "red"}); 

После того, как в первом уровне данных у нас есть 2 объекта, D3 будут созданы 2 группы для нас.

Я также использовал группы, чтобы установить цвета окружностей: если name является «мужским», круг синего цвета, в противном случае это красное:

.attr("fill", function(d){ return (d.name == "male") ? "blue" : "red"}); 

Теперь, когда созданы группы, мы создаем круги в соответствии с values в данных каждой группы, связывание данных следующим образом:

var circles = circlesGroups.selectAll(".circles") 
     .data(function(d){ return d.values}) 
     .enter() 
     .append("circle"); 

Здесь function(d){ return d.values} будет связывать данные с кругами в соответствии с объектами внутри values массивов.

И затем вы позиционируете свои круги. Это весь код, нажмите кнопку «запустить фрагмент кода», чтобы увидеть его:

var data = [ 
 
    {name: "male", 
 
    values: [{ x: 123,y: 234}, 
 
     { x: 432,y: 221}, 
 
     { x: 199,y: 56}] 
 
    }, 
 
    {name: "female", 
 
    values: [{ x: 223,y: 111}, 
 
     { x: 67,y: 288}, 
 
     { x: 19, y: 387}] 
 
    } 
 
]; 
 

 
var xScale = d3.scaleLinear().range([20, 380]) 
 
\t .domain([0, d3.max(data, function(d){ 
 
\t \t \t return d3.max(d.values, function(d){ 
 
\t \t \t \t return d.x; 
 
\t \t }) 
 
\t })]); 
 
\t \t 
 

 

 
var yScale = d3.scaleLinear().range([20, 380]) 
 
    .domain([0, d3.max(data, function(d){ 
 
\t \t \t return d3.max(d.values, function(d){ 
 
\t \t \t \t return d.y; 
 
\t \t }) 
 
\t })]); 
 

 
var xAxis = d3.axisBottom(xScale).tickSizeInner(-360); 
 
var yAxis = d3.axisLeft(yScale).tickSizeInner(-360); 
 

 
var svg = d3.select("body") 
 
\t .append("svg") 
 
\t .attr("width", 400) 
 
\t .attr("height", 400); 
 

 
svg.append("g") 
 
\t .attr("class", "x axis") 
 
\t .attr("transform", "translate(0,380)") 
 
\t .call(xAxis); 
 
\t 
 
svg.append("g") 
 
\t .attr("class", "y axis") 
 
\t .attr("transform", "translate(20,0)") 
 
\t .call(yAxis); 
 
\t 
 
var circlesGroups = svg.selectAll(".circlesGroups") 
 
\t .data(data) 
 
\t .enter() 
 
\t .append("g") 
 
\t .attr("fill", function(d){ return (d.name == "male") ? "blue" : "red"}); 
 
\t 
 
var circles = circlesGroups.selectAll(".circles") 
 
\t .data(function(d){ return d.values}) 
 
\t .enter() 
 
\t .append("circle"); 
 
\t \t 
 
circles.attr("r", 10) 
 
\t .attr("cx", function(d){ return xScale(d.x)}) 
 
\t .attr("cy", function(d){ return yScale(d.y)});
.axis path, line{ 
 
\t stroke: gainsboro; 
 
}
<script src="https://d3js.org/d3.v4.min.js"></script>

+0

Спасибо, это очень ясный пример, я узнал что-то новое :) – Shawn

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