Qual é a diferença entre D3 e dados?


199

Alguém pode explicar a diferença entre datum () e data () no D3.js. Vejo os dois sendo usados ​​e não sei por que você deve escolher um sobre o outro?

Respostas:


164

Encontrei a resposta correta aqui do próprio Mike:

D3 - como lidar com estruturas de dados JSON?

Se você deseja vincular seus dados a um único elemento SVG, use

(...).data([data])

ou

(...).datum(data)

Se você deseja vincular seus dados a vários elementos SVG

(...).data(data).enter().append("svg")

.....


Obrigado por isso! o fato de você colocar dados ([dados]) passando e matriz apenas me ajudou a perceber um bug que não consegui descobrir na semana passada! Muito obrigado ... sempre essas coisas estúpidas que estão erradas.
— Adam

22
data () realiza uma junção, datum () não.
— S3-4v

Lembre-se de que, se houver mais elementos da matriz de dados do que elementos SVG ao vincular dados enter(), o d3 vinculará o restante dos elementos da matriz aos elementos SVG recém-criados.
— aslantorret

49

Depois de analisar um pouco isso, descobri que as respostas aqui no SO não estão completas, pois só cobrem o caso quando você invoca selection.datae selection.datumcom um dataparâmetro de entrada . Mesmo nesse cenário, os dois se comportam de maneira diferente se a seleção é um único elemento e quando contém vários elementos. Além disso, esses dois métodos também podem ser chamados sem nenhum argumento de entrada, a fim de consultar os dados / dados vinculados na seleção; nesse caso, eles novamente se comportam de maneira diferente e retornam coisas diferentes.

Editar - Publiquei uma resposta um pouco mais detalhada para esta pergunta aqui , mas a postagem abaixo captura praticamente todos os pontos-chave sobre os dois métodos e como eles diferem entre si.

Ao fornecer data como argumento de entrada

  • selection.data(data)tentará executar um data-junção entre os elementos do dataarray com a seleção resultando na criação de enter(), exit()e update()seleções que você pode posteriormente operar. O resultado final disso é que, se você passar em uma matriz data = [1,2,3], é feita uma tentativa de associar cada elemento de dados individual (ou seja, dados) à seleção. Cada elemento da seleção terá apenas um único elemento de dado datavinculado a ele.

  • selection.datum(data)ignora completamente o processo de junção de dados. Isso simplesmente atribui a totalidade dataa todos os elementos na seleção como um todo, sem dividi-los, como no caso de junções de dados. Portanto, se você deseja vincular uma matriz inteira data = [1, 2, 3]a cada elemento DOM no seu selection, selection.datum(data)conseguirá isso.

Aviso: muitas pessoas acreditam que issoselection.datum(data)é equivalente,selection.data([data])mas isso só é verdade se selection contiver um único elemento . Seselectioncontiver vários elementos DOM,selection.datum(data)vinculará a totalidadedataa todos os elementos da seleção. Por outro lado,selection.data([data])apenas liga a totalidadedata ao primeiro elemento emselection. Isso é consistente com o comportamento de junção de dados deselection.data.

Ao fornecer nenhum dataargumento de entrada

  • selection.data()pegará o dado vinculado para cada elemento na seleção e os combinará em uma matriz retornada. Assim, se seu selectioninclui 3 elementos DOM com os dados "a", "b"e "c"obrigado a cada respectivamente, selection.data()retornos ["a", "b", "c"]. É importante observar que, se selectioné um único elemento com (por exemplo) o dado "a"vinculado a ele, ele selection.data()retornará ["a"]e não "a"como alguns podem esperar.

  • selection.datum()só faz sentido para uma única seleção, pois é definida como retornando o dado vinculado ao primeiro elemento da seleção. Portanto, no exemplo acima, com a seleção que consiste em elementos DOM com dados vinculados de "a", "b"e "c", selection.datum()simplesmente retornaria "a".

Note-se que mesmo se selectiontem um único elemento, selection.datum()e selection.data()retornar valores diferentes. O primeiro retorna o dado vinculado para a seleção ( "a"no exemplo acima) enquanto o último retorna o dado vinculado dentro de uma matriz ( ["a"]no exemplo acima).

Esperamos que isso ajude a esclarecer como selection.datae selection.datum()diferir um do outro ao fornecer dados como um argumento de entrada e ao consultar o dado vinculado por não fornecer nenhum argumento de entrada.

PS - A melhor maneira de entender como isso funciona é começar com um documento HTML em branco no Chrome, abrir o console e tentar adicionar alguns elementos ao documento e começar a vincular dados usando selection.datae selection.datum. Às vezes, é muito mais fácil "grok" algo fazendo do que lendo.


O HamsterHuey já mostrou isso, mas pode ser um lembrete útil para lembrar que "datum" é singular e "data" é plural. Portanto, .datum se aplica às informações associadas a um único elemento.
— Visio Guy

42

Aqui estão alguns bons links:

Por este último:

# selection.data([values[, key]])

Une a matriz de dados especificada à seleção atual. Os valores especificados são uma matriz de valores de dados, como uma matriz de números ou objetos, ou uma função que retorna uma matriz de valores.

...

# selection.datum([value])

Obtém ou define os dados associados a cada elemento selecionado. Diferentemente do método selection.data, esse método não calcula uma junção (e, portanto, não computa as seleções de entrada e saída).


11
dado essas definições - eu ainda estou confuso por que você iria precisar / querer usar datum ()
— josephmisiti

Mais um exemplo que pode ajudar a tornar as coisas mais claras: ngokevin.com/blog/d3 . NOTAS: 1) A definição de Kevin: "O dado é o dado vinculado ao elemento". 2) Observe como nos exemplos de Kevin "incorporamos" o conjunto de dados com "data ()" ... mas "usamos" um subconjunto referenciando um "datum ()".
— paulsm4

5

Eu acho que a explicação dada por HamsterHuey é a melhor até agora. Para expandir e fornecer uma representação visual das diferenças, criei um documento de exemplo que ilustra pelo menos parte das diferenças entre datae datum.

A resposta abaixo é mais uma opinião derivada do uso desses métodos, mas fico feliz em ser corrigido se estiver errado.

Este exemplo pode ser executado abaixo ou neste Fiddle .

const data = [1,2,3,4,5];
const el = d3.select('#root');

 el
  .append('div')
  .classed('a', true)
  .datum(data)
  .text(d => `node => data: ${d}`);

const join= el
.selectAll('div.b')
.data(data);

join
.enter()
.append('div')
.classed('b', true)
.text((d, i) => `node-${i + 1} => data: ${d}`)

Eu acho que datumé mais simples de entender, uma vez que não faz uma junção, mas é claro que isso também significa que ele tem diferentes casos de uso.

Para mim, uma grande diferença - embora exista mais - é o fato de que dataé apenas a maneira natural de fazer atualizações (ao vivo) em um gráfico d3, pois todo o padrão de entrada / atualização / saída simplifica quando você o obtém.

datumpor outro lado, parece-me mais adequado para representações estáticas. No exemplo abaixo, por exemplo, eu poderia obter o mesmo resultado, fazendo um loop na matriz original e acessando os dados pelo índice da seguinte forma:

data.map((n, i) => {
 el
  .append('div')
  .classed('a', true)
  .datum(data)
  .text(d => `node-${n} => data: ${d[i]}`);
});

Experimente aqui: https://jsfiddle.net/gleezer/e4m6j2d8/6/

Mais uma vez, acho que isso é muito mais fácil de entender, pois você se livra da carga mental proveniente do padrão de entrada / atualização / saída, mas assim que precisar atualizar ou alterar a seleção, certamente será melhor recorrer .data().

const data = [1,2,3,4,5];
const el = d3.select('#root');

 el
  .append('div')
  .classed('a', true)
  .datum(data)
  .text(d => `node => data: ${d}`);

const join= el
.selectAll('div.b')
.data(data);

join
.enter()
.append('div')
.classed('b', true)
.text((d, i) => `node-${i + 1} => data: ${d}`)
/* Ignore all the css */
html {
  font-family: arial;
}

.l {
  width: 20px;
  height: 20px;
  display: inline-block;
  vertical-align: middle;
  margin: 10px 0;
}
.l-a {
  background: #cf58e4;
}
.l-b {
  background:  #42e4e4;
}

.a {
  border-bottom: 2px solid #cf58e4;
}

.b {
  border-bottom: 2px solid #42e4e4;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.6.0/d3.min.js"></script>


<div style="margin-bottom: 20px;">
  <span class="l l-a"></span> .datum() <br />
  <span class="l l-b"></span> .data()
</div>

<div id="root"></div>

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.