d3.js, как сгенерировать древовидную иерархию из CSV или таблицы - PullRequest
0 голосов
/ 26 апреля 2018

У меня есть CSV со следующими данными:

world,country,state

World,US,CA

World,US,NJ

World,INDIA,OR

World,INDIA,AP

Мне нужно преобразовать в древовидную иерархию, как показано ниже:

{

"name": "World",
"children": [
  { "name": "US",
      "children": [
       { "name": "CA" },
       { "name": "NJ" }
     ]
  },
  { "name": "INDIA",
      "children": [
      { "name": "OR" },
      { "name": "TN" }
     ]
  }

] };

Используя d3.nest, я могу получить только массив json, а не дерево с именем 'children' в нем. Что-нибудь еще, что мне нужно сделать? Чтение API не очень помогло, и я не могу найти фрагмент кода, который выполняет преобразование, где бы я ни искал.

1 Ответ

0 голосов
/ 26 апреля 2018

Исходя из вашего другого вопроса , я предполагаю, что вы хотите использовать эти иерархические данные в иерархической структуре d3

После прочтения d3.csv / tsv / dsv и т. Д. Вы получите массив с такими объектами:

[
  { "world": "World","country": "US","state": "CA" },
  { "world": "World","country": "US","state": "NJ" },
  { "world": "World","country": "INDIA","state": "OR" },
  { "world": "World","country": "INDIA","state": "AP"}
]

Мы можем использовать гнездо d3, чтобы получить большую часть полезного дерева для иерархии d3 (дерево, дендограмма и т. Д.):

{ 
  "key": "World", "values": [
    {
      "key": "US", "values": [
        { "world": "World", "country": "US", "state": "CA" },
        { "world": "World", "country": "US", "state": "NJ" }
      ]
    },
    {
      "key": "INDIA", "values": [
        { "world": "World", "country": "INDIA", "state": "OR" }, 
        { "world": "World", "country": "INDIA", "state": "AP" }
      ]
    }
  ]
}

Это было сделано с:

var nestedData = d3.nest()
 .key(function(d) { return d.world; })
 .key(function(d) { return d.country; })
 .entries(data);

Это создает массив, где каждый элемент в массиве является корнем. Чтобы получить json выше с помощью d3.nest (), нам нужно получить первый элемент в массиве, в данном случае, nestedData[0];. Также обратите внимание, что нам обычно не нужно вкладывать самый низкий уровень, в этом случае состояние

Теперь мы можем подать эти данные в d3.hierarchy , чтобы получить иерархию, используемую для визуализаций. Если вы посмотрите на документацию, мы имеем структуру данных, идентичную примеру, за исключением того, что наши дочерние элементы содержатся в свойстве, называемом «значения», а не «дочерние элементы». Не беспокойтесь, d3.hierarchy позволяет нам задать имя свойства, которое содержит дочерние элементы:

d3.hierarchy (data [, children])

...

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

function children(d) { return d.children; }

Итак, чтобы взять вышеупомянутые данные, созданные из d3.nest, давайте передадим их в d3.hierarchy:

var root = d3.hierarchy(nestedData[0],function(d) { return d.values; })

Теперь у нас есть набор данных, который можно передать в любой иерархический макет d3:

var data = [
 { "world": "World","country": "US","state": "CA" }, 
 { "world": "World","country": "US","state": "NJ" },
 { "world": "World","country": "INDIA","state": "OR" },
 { "world": "World","country": "INDIA","state": "AP"}
];

 
var nestedData = d3.nest()
  .key(function(d) { return d.world; })
  .key(function(d) { return d.country; })
  .entries(data);
	
var root = d3.hierarchy(nestedData[0], function(d) { return d.values; })

// Now draw the tree:

var width = 500;
var height = 400;

margin = {left: 10, top: 10, right: 10, bottom: 10}

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

	  
var tree = d3.tree()
    .size([height-margin.top-margin.bottom,width-margin.left-margin.right]);

 var link = g.selectAll(".link")
    .data(tree(root).links())
    .enter().append("path")
      .attr("class", "link")
      .attr("d", d3.linkHorizontal()
          .x(function(d) { return d.y; })
          .y(function(d) { return d.x; }));

  var node = g.selectAll(".node")
    .data(root.descendants())
    .enter().append("g")
      .attr("class", function(d) { return "node" + (d.children ? " node--internal" : " node--leaf"); })
      .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })

  node.append("circle")
      .attr("r", 2.5);
	  
  node.append("text")
     .text(function(d) { return d.data.key; })
	 .attr('y',-10)
	 .attr('x',-10)
	 .attr('text-anchor','middle');
path {
  fill:none;
  stroke: steelblue;
  stroke-width: 1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>

Вот пример с фактическим CSV и еще несколькими строками и уровнями.


Если структура данных csv была другой, содержащей родительские и дочерние пары, то она будет выглядеть примерно так, когда-то проанализированная с d3.csv / tsv / dsv:

[
 {parent: "", name: "World"},
 {parent: "World", name:"US"},
 {parent: "World", name:"India"},
 {parent: "India", name:"OR" },
 {parent: "India", name:"AP" },
 {parent: "US", name:"CA" },
 {parent: "US", name:"WA" }
]

При этом мы можем использовать d3.stratify вместо комбинации d3.nest и d3.hierarchy:

var data = [
 {parent: "", name: "World"},
 {parent: "World", name:"US"},
 {parent: "World", name:"India"},
 {parent: "India", name:"OR" },
 {parent: "India", name:"AP" },
 {parent: "US", name:"CA" },
 {parent: "US", name:"WA" }
];

// manipulate data:

var root = d3.stratify()
  .id(function(d) { return d.name; })
  .parentId(function(d) { return d.parent; })
  (data);
  
// Now draw the tree:

var width = 500;
var height = 400;

margin = {left: 10, top: 10, right: 10, bottom: 10}

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

	  
var tree = d3.tree()
    .size([height-margin.top-margin.bottom,width-margin.left-margin.right]);

 var link = g.selectAll(".link")
    .data(tree(root).links())
    .enter().append("path")
      .attr("class", "link")
      .attr("d", d3.linkHorizontal()
          .x(function(d) { return d.y; })
          .y(function(d) { return d.x; }));

  var node = g.selectAll(".node")
    .data(root.descendants())
    .enter().append("g")
      .attr("class", function(d) { return "node" + (d.children ? " node--internal" : " node--leaf"); })
      .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })

  node.append("circle")
      .attr("r", 2.5);
	  
  node.append("text")
     .text(function(d) { return d.data.name; })
	 .attr('y',-10)
	 .attr('x',-10)
	 .attr('text-anchor','middle');
path {
  fill: none;
  stroke: steelblue;
  stroke-width: 1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...