Pergunta

Eu tenho um arquivo tsv com um conteúdo simples de "tipo" "contagem" como este:

type    count
level1/level2/level3/Foo    24
level1/level2/level3/Bar    2
level1/level2/Baz   28
level1/level2/Quz   3
...

O level strings podem ser qualquer String, apenas as nomeei assim aqui, para transmitir o significado.O último elemento do tipo, Foo, Bar, etc.podem ser considerados as folhas dos dados.

Usando d3, quero transformar isso em um diagrama sunburst.Para fazer isso, eu uso o d3.nest função para dividir o tipo nas barras.

d3.tsv("data.tsv", function(error, data) {
  data.forEach(function(d) {
    d.count = +d.count;
  });

  // define key functions for a depth up to 4 
  var nestedData = d3.nest()
     .key(function(d) { return level(d.type, 2); })
     .key(function(d) { return level(d.type, 3); })
     .key(function(d) { return level(d.type, 4); })
     .entries(data);

  // create the key for a specified level 
  function level(type, l) {
     var parts = type.split("/");
     var result = "";
     for (i = 0; i < l && i < parts.length; i++) {
        result += parts[i];
        if (i < l-1 && i < parts.length-1) {
            result += "/";
        }
     }
     return result;
  }
  ...

A questão aqui é que o resultado nestedData sempre tem as entradas/folhas na profundidade 4.Nos dados de exemplo você pode ver que as folhas podem estar em qualquer profundidade.

Como posso construir dados aninhados para que as entradas possam ocorrer em qualquer profundidade, não apenas em uma profundidade predefinida?

Foi útil?

Solução

Desde d3.nest faz com que você registre as chaves de aninhamento com antecedência, antes de ligar nest.entries não há como fazer um aninhamento com um número variável de níveis especificando tudo antecipadamente.

Uma coisa que pode funcionar é usar recursivamente um ninho.rollup função para controlar a aparência dos valores em cada nível.Dentro do seu rollup você pode decidir se cada elemento de entrada deve ser um novo d3.nest contendo o próximo nível de detalhe ou se deveria ser um nó folha.

Aqui está uma explicação aproximada (assume level1 estará sempre presente):

function rollupFn(group) {
    var leaves = [],
        groups = [];

    // Split the items into leaves and groups
    group.forEach(function(item) {
        // First eliminate level already accounted for by d3.nest key
        item.type = item.type.substr(item.type.indexOf('/')+1);

        if (item.type.indexOf('/') > -1) {
            groups.push(item);
        } else {
            leaves.push(item);
        }
    });

    // Convert the "group" items into a d3.nest object
    groups = d3.nest().key(function(d) {
            return d.type.split('/')[0];
        })
        .rollup(rollupFn)
        .entries(groups);

    var results = [];
    if (groups.length > 0) { results.push(groups); }
    if (leaves.length > 0) { results.push(leaves); }
    return results;
};

var nestedData = d3.nest()
    .key(function(d) { return "level1" })  // optional: first group contains everything
    .rollup(rollupFn)
    .entries(data);

Os valores em cada nível consistirão em um elemento contendo um objeto d3.nest representando todos os níveis inferiores seguidos por todos os nós folha.Se não houver mais níveis, a matriz de valores será composta por todos os nós folha.

Aqui está um código funcional que você pode percorrer: http://jsfiddle.net/S8aMU/10

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top