Jaka jest różnica między danymi D3 a danymi?


199

Czy ktoś może wyjaśnić różnicę między datum () a data () w D3.js? Widzę, że oba są używane i nie jestem pewien, dlaczego powinieneś wybrać jedno z nich?

Odpowiedzi:


164

Znalazłem tutaj poprawną odpowiedź od samego Mike'a:

D3 - jak radzić sobie ze strukturami danych JSON?

Jeśli chcesz powiązać swoje dane z jednym elementem SVG, użyj

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

lub

(...).datum(data)

Jeśli chcesz powiązać swoje dane z wieloma elementami SVG

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

.....


Dziękuję Ci za to! fakt, że umieściłeś przekazywanie danych ([data]) i tablicę, pomógł mi zdiagnozować błąd, którego nie mogłem znaleźć w ostatnim tygodniu! Dziękuję bardzo ... zawsze takie głupie rzeczy, które są złe.
— Adam

22
data () wykonuje łączenie, datum () nie.
— s3-4v

Pamiętaj tylko, że w przypadku, gdy istnieje więcej elementów tablicy danych niż elementów SVG podczas wiązania danych enter(), d3 wiąże resztę elementów tablicy z nowo utworzonymi elementami SVG.
— aslantorret

49

Po dokładnym przyjrzeniu się temu stwierdziłem, że odpowiedzi tutaj na SO nie są kompletne, ponieważ obejmują one tylko przypadek, gdy wywołujesz selection.datai selection.datumz dataparametrem wejściowym . Nawet w tym scenariuszu oba zachowują się inaczej, jeśli zaznaczenie jest pojedynczym elementem, a jeśli zawiera wiele elementów. Co więcej, obie te metody można również wywoływać bez żadnych argumentów wejściowych w celu przeszukiwania powiązanych danych / danych w zaznaczeniu, w którym to przypadku ponownie zachowują się inaczej i zwracają różne rzeczy.

Edit - napisałem nieco bardziej szczegółową odpowiedź na to pytanie tutaj , ale post poniżej dość dużo przechwytuje wszystkie najważniejsze punkty dotyczące tych dwóch metod i jak różnią się one od siebie.

Podając data jako argument wejściowy

  • selection.data(data)dokładają wszelkich starań, aby wykonać dane dołącz pomiędzy elementami datatablicy z wyboru, w wyniku utworzenia enter(), exit()oraz update()pozycje, które można następnie operować. Efektem końcowym tego jest, jeśli przejdziesz do tablicy data = [1,2,3], podejmowana jest próba połączenia każdego elementu danych (tj. Układu odniesienia) z zaznaczeniem. Każdy element zaznaczenia będzie miał związany tylko jeden element odniesienia data.

  • selection.datum(data)całkowicie pomija proces łączenia danych. To po prostu przypisuje całość datawszystkim elementom zaznaczenia jako całości, bez dzielenia go, jak w przypadku łączenia danych. Więc jeśli chcesz powiązać całą tablicę data = [1, 2, 3]z każdym elementem DOM w twoim selection, wtedy selection.datum(data)to osiągniesz.

Ostrzeżenie: wiele osób uważa, żeselection.datum(data)jest to równoważne,selection.data([data])ale jest to prawdą tylko wtedy, gdy selection zawiera jeden element . Jeśliselectionzawiera wiele elementów DOM, wówczasselection.datum(data)wiąże całość zdatakażdym elementem w zaznaczeniu. W przeciwieństwie,selection.data([data])wiąże tylko całość zdata pierwszym elementem wselection. Jest to zgodne z zachowaniem łączenia danychselection.data.

Gdy nie datapodajesz argumentu wejściowego

  • selection.data()weźmie powiązane dane dla każdego elementu w zaznaczeniu i połączy je w zwracaną tablicę. Tak więc, jeśli selectionskłada się z 3 elementów DOM z danymi "a", "b"a "c"połączone ze sobą odpowiednio selection.data()zwrotów ["a", "b", "c"]. Ważne jest, aby zauważyć, że jeśli selectionjest to pojedynczy element z (na przykład) "a"związaną z nim datum , wówczas selection.data()powróci ["a"]i nie będzie, "a"jak niektórzy mogą się spodziewać.

  • selection.datum()ma sens tylko dla pojedynczego zaznaczenia, ponieważ jest zdefiniowany jako powrót układu odniesienia związanego z pierwszym elementem zaznaczenia. Tak więc w powyższym przykładzie z wyboru składający się z elementów DOM ze związanym z odniesienia "a", "b"i "c", selection.datum()po prostu wrócić "a".

Zauważ, że nawet jeśli selectionma jeden element selection.datum()i selection.data()zwracaj różne wartości. Pierwszy zwraca związany punkt odniesienia dla wyboru ( "a"w powyższym przykładzie), podczas gdy drugi zwraca związany punkt odniesienia w tablicy ( ["a"]w powyższym przykładzie).

Mam nadzieję, że to pomaga wyjaśnić, w jaki sposób selection.datai selection.datum()różnią się od siebie zarówno w przypadku udostępniania danych jako argument wejściowy i podczas odpytywania dla związanego odniesienia nie dostarczając żadnych argumentów wejściowych.

PS - Najlepszym sposobem na zrozumienie, jak to działa, jest rozpoczęcie od pustego dokumentu HTML w Chrome i otwarcie konsoli i próba dodania kilku elementów do dokumentu, a następnie rozpoczęcie wiązania danych za pomocą selection.datai selection.datum. Czasami o wiele łatwiej „coś” zrobić, robiąc, niż czytając.


HamsterHuey już to pokazał, ale pomocne może być przypomnienie, że „dane” są w liczbie pojedynczej, a „dane” w liczbie mnogiej. Dlatego .datum dotyczy informacji powiązanych z jednym elementem.
— Visio Guy

42

Oto kilka dobrych linków:

Zgodnie z tym ostatnim:

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

Łączy podaną tablicę danych z bieżącym wyborem. Podane wartości to tablica wartości danych, na przykład tablica liczb lub obiektów, lub funkcja zwracająca tablicę wartości.

...

# selection.datum([value])

Pobiera lub ustawia powiązane dane dla każdego wybranego elementu. W przeciwieństwie do metody selection.data, ta metoda nie oblicza złączenia (a zatem nie oblicza wejść i wyjść z selekcji).


11
biorąc pod uwagę te definicje - Jestem nadal mylone dlaczego byś kiedykolwiek potrzebują / chcą wykorzystywać układ odniesienia ()
— josephmisiti

Jeszcze jeden przykład, który może pomóc w wyjaśnieniu : ngokevin.com/blog/d3 . UWAGI: 1) Definicja Kevina: „Daną odniesienia są dane powiązane z elementem”. 2) Zwróć uwagę, jak w przykładach Kevina „włączamy” zestaw danych do „data ()” ... ale „używamy” podzestawu, odwołując się do „datum ()”.
— paulsm4

5

Myślę, że wyjaśnienie podane przez HamsterHuey jest jak dotąd najlepsze. Aby go rozwinąć i przedstawić wizualnie różnice, stworzyłem przykładowy dokument, który ilustruje przynajmniej część różnic między datai datum.

Poniższa odpowiedź jest bardziej opinią wynikającą z zastosowania tych metod, ale cieszę się, że mogę je poprawić, jeśli się mylę.

Ten przykład można uruchomić poniżej lub w tym skrzypce .

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}`)

Myślę, że datumłatwiej jest to uchwycić, ponieważ nie wykonuje łączenia, ale oczywiście oznacza to również, że ma różne przypadki użycia.

Dla mnie jedną wielką różnicą - choć jest ich więcej - to fakt, że datajest to naturalny sposób wykonywania aktualizacji (na żywo) na wykresie d3, ponieważ cały wzorzec wchodzenia / aktualizowania / wychodzenia sprawia, że ​​jest to proste, gdy tylko je dostaniesz.

datumz drugiej strony wydaje mi się, że lepiej nadaje się do przedstawień statycznych. W poniższym przykładzie mogę na przykład osiągnąć ten sam wynik, zapętlając oryginalną tablicę i uzyskując dostęp do danych przez indeks w ten sposób:

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

Wypróbuj tutaj: https://jsfiddle.net/gleezer/e4m6j2d8/6/

Ponownie myślę, że jest to o wiele łatwiejsze do uchwycenia, ponieważ uwalniasz się od mentalnego obciążenia wynikającego ze schematu wchodzenia / aktualizowania / wychodzenia, ale gdy tylko będziesz musiał zaktualizować lub zmienić wybór, na pewno lepiej będzie się uciekać .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>

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.