Как мне ввести массив в D3.js? - PullRequest
0 голосов
/ 22 марта 2019

Есть ли способ ввести весь массив из моего набора данных в D3.js?Или я должен очистить его перед вводом?

Пример моего набора данных .jason здесь:

[
{
    "promoter": "Vigun01",
    "upstream": "[2, 57, 150, 376]"
},
{
    "promoter": "Vigun01",
    "upstream": "[500, 732, 765]"
},
{
    "promoter": "Vigun01",
    "upstream": "[675]"
},
{
    "promoter": "Vigun02",
    "upstream": "[623]"
},
{
    "promoter": "Vigun03",
    "upstream": "[133, 601]"
},
{
    "promoter": "Vigun04",
    "upstream": "[599, 650]"
},
{
    "promoter": "Vigun05",
    "upstream": "[50, 789]"
}
]

и мой сценарий в D3.js находится здесь:

var svg = d3.select("#chart-area")
.append("svg")
    .attr("width", "400")
    .attr("height", "400");

d3.json("data/dataset.json").then(function(data){

data.forEach(d => {
    d.upstream = +d.upstream;
});
console.log(data);

var y = d3.scaleBand()
    .domain(data.map(function(d){
        return d.promoter;
    }))
    .range([0, 400])
    .paddingInner(0.2)
    .paddingOuter(0.2);

var x = d3.scaleLinear()
    .domain([0,1000])
    .range([0,400]);

var line = svg.selectAll("line")
    .data(data);

line.enter()
    .append('line')
        .attr('x1', 0)
        .attr('y1', (d,i)=>y(d.promoter))
        .attr('x2', 400)
        .attr('y2', (d,i)=>y(d.promoter))
        .attr('stroke-width', 1)
        .attr('stroke', 'black');


var circle = svg.selectAll("circle")
        .data(data)
    .enter()
        .append("circle")
        .attr("cy", function(d){
            return y(d.promoter)
        })
        .attr("cx", function(d){
           return x(d.upstream)
        })
        .attr("r", 5)
        .attr("fill", function(d) {
            return "black";
        });


}).catch(function(error){
    console.log(error)
});

Я могу рисовать отдельные входы, например ("Vigun01", "10"), но я не могу, если у меня есть весь массив.

Это нормально для меня, если конвертировать ("Vigun01", "[1,2,3,4]") во многие входы, такие как ("Vigun01", "1"), ("Vigun01", "2"), (" Vigun01 "," 3 "), (" Vigun01 "," 4 "), но как мне сделать это в моем наборе данных?

1 Ответ

1 голос
/ 22 марта 2019

Есть несколько вещей, которые нужно отрегулировать:

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

Ваш код:

data.forEach(d => {
d.upstream = +d.upstream;
});

не преобразует вашу строку в массив или в значащее число. Это приведет к NaN.

  1. Поскольку вы хотите нарисовать круги для каждого элемента вашего внешнего массива JSON на одной строке, но изменить положение x на основе значений массива значений в восходящем направлении, я предлагаю разбить создание элемента круга на 2 этапа.

Сначала вы создаете элемент g для каждого промоутера, например:

var circleGroups = svg.selectAll("g.circles")
  .data(data)
    .enter()
    .append("g")
    .attr("class", "circles"); 
  1. Затем вы создаете для каждого элемента группы набор окружностей, соответствующих этому промоутеру. Для этого вам нужно немного скорректировать свои данные, а затем объединить данные с этим.

создать новые массивы для кругов того же промоутера:

  function getCircleData(d) {
  var cdata = d.upstream.map (function(ele) { 
    return {upstream: ele, promoter: d.promoter};
  });
  return cdata; 
  }

и объединение данных для кругов:

    var circle = circleGroups.selectAll("circle")
        .data(getCircleData)
    .enter()
        .append("circle")
        .attr("cy", function(d){
            return y(d.promoter)
        })
        .attr("cx", function(d){
           return x(d.upstream)
        })
        .attr("r", 5)
        .attr("fill", function(d) {
            return "black";
        });

Вот полный рабочий код. Я только заменил ваш AJAX-вызов установкой массива в функции.

    var svg = d3.select("body").append("svg")
      .attr("width", 960)
      .attr("height", 500)

// d3.json("data/dataset.json").then(function(data){
    let data = getData();

    /*
data.forEach(d => {
    d.upstream = +d.upstream;
});
console.log(data);
*/

var y = d3.scaleBand()
    .domain(data.map(function(d){
        return d.promoter;
    }))
    .range([0, 400])
    .paddingInner(0.2)
    .paddingOuter(0.2);

var x = d3.scaleLinear()
    .domain([0,1000])
    .range([0,400]);

var line = svg.selectAll("line")
    .data(data);

line.enter()
    .append('line')
        .attr('x1', 0)
        .attr('y1', (d,i)=>y(d.promoter))
        .attr('x2', 400)
        .attr('y2', (d,i)=>y(d.promoter))
        .attr('stroke-width', 1)
        .attr('stroke', 'black');


    var circleGroups = svg.selectAll("g.circles")
      .data(data)
    	.enter()
    	.append("g")
    	.attr("class", "circles");

    var circle = circleGroups.selectAll("circle")
            .data(getCircleData)
        .enter()
            .append("circle")
            .attr("cy", function(d){
                return y(d.promoter)
            })
            .attr("cx", function(d){
               return x(d.upstream)
            })
            .attr("r", 5)
            .attr("fill", function(d) {
                return "black";
            });
   
    function getCircleData(d) {
      var cdata = d.upstream.map (function(ele) { 
        return {upstream: ele, promoter: d.promoter};
      });
      return cdata; 
    }
    
    function getData() {
      var data = [
      {
          "promoter": "Vigun01",
          "upstream": [2, 57, 150, 376]
      },
      {
          "promoter": "Vigun01",
          "upstream": [500, 732, 765]
      },
      {
          "promoter": "Vigun01",
          "upstream": [675]
      },
      {
          "promoter": "Vigun02",
          "upstream": [623]
      },
      {
          "promoter": "Vigun03",
          "upstream": [133, 601]
      },
      {
          "promoter": "Vigun04",
          "upstream": [599, 650]
      },
      {
          "promoter": "Vigun05",
          "upstream": [50, 789]
      }
      ];
      return data;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
...