Sự khác biệt dữ liệu D3 so với dữ liệu là gì?


199

Ai đó có thể vui lòng giải thích sự khác biệt giữa datum () và data () trong D3.js không? Tôi thấy cả hai đang được sử dụng và tôi không chắc tại sao bạn nên chọn cái này hơn cái kia?

Câu trả lời:


164

Tôi tìm thấy câu trả lời chính xác ở đây từ chính Mike:

D3 - làm thế nào để đối phó với các cấu trúc dữ liệu JSON?

Nếu bạn muốn liên kết dữ liệu của mình với một yếu tố SVG, hãy sử dụng

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

hoặc là

(...).datum(data)

Nếu bạn muốn liên kết dữ liệu của mình với nhiều yếu tố SVG

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

.....


Cảm ơn vì điều này! thực tế là bạn đưa dữ liệu ([dữ liệu]) đi qua và mảng chỉ giúp tôi nhận ra một lỗi mà tôi không thể tìm ra trong tuần qua! Cảm ơn bạn rất nhiều ... luôn luôn những điều ngu ngốc như vậy là sai.
Adam

22
data () thực hiện nối, datum () thì không.
s3-4v

Chỉ cần lưu ý, trong trường hợp nếu có nhiều phần tử mảng dữ liệu hơn phần tử SVG khi liên kết dữ liệu với enter(), d3 sẽ liên kết phần còn lại của phần tử mảng với phần tử SVG mới được tạo.
aslantorret

49

Sau khi xem xét điều này một chút, tôi thấy rằng các câu trả lời ở đây trên SO không đầy đủ vì chúng chỉ bao gồm trường hợp khi bạn gọi selection.dataselection.datumvới một datatham số đầu vào . Ngay cả trong kịch bản đó, cả hai hành xử khác nhau nếu lựa chọn là một yếu tố duy nhất so với khi nó chứa nhiều yếu tố. Hơn nữa, cả hai phương thức này cũng có thể được gọi mà không có bất kỳ đối số đầu vào nào để truy vấn dữ liệu / mốc dữ liệu bị ràng buộc trong lựa chọn, trong trường hợp chúng một lần nữa hành xử khác nhau và trả về những thứ khác nhau.

Chỉnh sửa - Tôi đã đăng một câu trả lời chi tiết hơn một chút cho câu hỏi này ở đây , nhưng bài đăng dưới đây nắm bắt được tất cả các điểm chính liên quan đến hai phương pháp và cách chúng khác nhau.

Khi cung cấp data làm đối số đầu vào

  • selection.data(data)sẽ cố gắng thực hiện một dữ liệu tham gia giữa các yếu tố của datamảng với các lựa chọn kết quả trong việc tạo ra enter(), exit()update()các lựa chọn mà bạn sau đó có thể hoạt động trên. Kết quả cuối cùng của điều này là nếu bạn truyền vào một mảng data = [1,2,3], một nỗ lực được thực hiện để nối từng phần tử dữ liệu riêng lẻ (tức là mốc) với lựa chọn. Mỗi phần tử của lựa chọn sẽ chỉ có một phần tử chuẩn duy nhất được dataliên kết với nó.

  • selection.datum(data)bỏ qua quá trình tham gia dữ liệu hoàn toàn. Điều này chỉ đơn giản là gán toàn bộ datacho tất cả các thành phần trong vùng chọn mà không tách nó ra như trong trường hợp nối dữ liệu. Vì vậy, nếu bạn muốn liên kết toàn bộ một mảng data = [1, 2, 3]với mọi thành phần DOM trong của bạn selection, thì selection.datum(data)sẽ đạt được điều này.

Cảnh báo: Nhiều người cho rằng điều đóselection.datum(data)tương đươngselection.data([data])nhưng điều này chỉ đúng nếu selection chứa một yếu tố duy nhất . Nếuselectionchứa nhiều phần tử DOM, thìselection.datum(data)sẽ liên kết toàn bộdatavới mọi phần tử trong phần chọn. Ngược lại,selection.data([data])chỉ liên kết toàn bộdata với phần tử đầu tiên trongselection. Điều này phù hợp với hành vi tham gia dữ liệu củaselection.data.

Khi cung cấp không có datađối số đầu vào

  • selection.data()sẽ lấy mốc thời gian ràng buộc cho từng thành phần trong vùng chọn và kết hợp chúng thành một mảng được trả về. Vì vậy, nếu bạn selectionbao gồm 3 yếu tố DOM với dữ liệu "a", "b""c"bị ràng buộc với nhau tương ứng, selection.data()lợi nhuận ["a", "b", "c"]. Điều quan trọng cần lưu ý là nếu selectionlà một phần tử duy nhất với (bằng ví dụ) thì mốc chuẩn "a"bị ràng buộc với nó, sau đó selection.data()sẽ trả về ["a"]và không "a"như một số người có thể mong đợi.

  • selection.datum()chỉ có ý nghĩa đối với một lựa chọn vì nó được định nghĩa là trả về mốc chuẩn bị ràng buộc với phần tử đầu tiên của lựa chọn. Vì vậy, trong ví dụ trên với lựa chọn bao gồm các phần tử DOM với dữ kiện ràng buộc của "a", "b""c", selection.datum()chỉ đơn giản là sẽ quay trở lại "a".

Lưu ý rằng ngay cả khi selectioncó một phần tử duy nhất selection.datum()selection.data()trả về các giá trị khác nhau. Cái trước trả về mốc dữ liệu bị ràng buộc cho lựa chọn ( "a"trong ví dụ ở trên) trong khi cái sau trả về mốc dữ liệu bị ràng buộc trong một mảng ( ["a"]trong ví dụ trên).

Hy vọng rằng điều này sẽ giúp làm rõ cách thức selection.dataselection.datum()khác biệt với nhau cả khi cung cấp dữ liệu dưới dạng đối số đầu vào và khi truy vấn dữ liệu bị ràng buộc bằng cách không cung cấp bất kỳ đối số đầu vào nào.

PS - Cách tốt nhất để hiểu cách thức hoạt động của nó là bắt đầu với một tài liệu HTML trống trong Chrome và mở bảng điều khiển và thử thêm một vài yếu tố vào tài liệu và sau đó bắt đầu ràng buộc dữ liệu bằng cách sử dụng selection.dataselection.datum. Đôi khi, thật dễ dàng để "mò mẫm" một cái gì đó bằng cách làm hơn là đọc.


HamsterHuey đã cho thấy điều này rồi, nhưng nó có thể là một lời nhắc hữu ích để nhớ lại rằng "mốc" là số ít và "dữ liệu" là số nhiều. Do đó .datum áp dụng cho thông tin liên quan đến một yếu tố.
Visio Guy

42

Dưới đây là một số liên kết tốt:

Mỗi cái sau:

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

Tham gia mảng dữ liệu đã chỉ định với lựa chọn hiện tại. Các giá trị được chỉ định là một mảng các giá trị dữ liệu, chẳng hạn như một mảng các số hoặc đối tượng hoặc một hàm trả về một mảng các giá trị.

...

# selection.datum([value])

Nhận hoặc đặt dữ liệu ràng buộc cho từng thành phần được chọn. Không giống như phương thức select.data, phương thức này không tính toán một phép nối (và do đó không tính toán các lựa chọn nhập và thoát).


11
đưa ra những định nghĩa đó - tôi vẫn bối rối tại sao bạn lại cần / muốn sử dụng datum ()
josephmisiti

Một ví dụ nữa có thể giúp làm cho mọi thứ rõ ràng hơn: ngokevin.com/blog/d3 . GHI CHÚ: 1) Định nghĩa của Kevin: "Dữ liệu là dữ liệu được liên kết với phần tử." 2) Lưu ý cách trong các ví dụ của Kevin, chúng tôi "kết hợp" tập dữ liệu với "data ()" ... nhưng chúng tôi "sử dụng" một tập hợp con bằng cách tham chiếu "datum ()".
paulsm4

5

Tôi nghĩ rằng lời giải thích được đưa ra bởi HamsterHuey là tốt nhất cho đến nay. Để mở rộng về nó và đưa ra một đại diện trực quan về sự khác biệt, tôi đã tạo một tài liệu mẫu minh họa ít nhất một phần của sự khác biệt giữa datadatum.

Câu trả lời dưới đây có nhiều ý kiến ​​xuất phát từ việc sử dụng các phương pháp này, nhưng tôi rất vui khi được sửa nếu tôi sai.

Ví dụ này có thể được chạy bên dưới hoặc trong Fiddle này .

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

Tôi nghĩ rằng datumviệc nắm bắt đơn giản hơn vì nó không tham gia, nhưng tất nhiên điều này cũng có nghĩa là nó có các trường hợp sử dụng khác nhau.

Đối với tôi một sự khác biệt lớn - mặc dù có nhiều hơn - đó là thực tế datachỉ là cách tự nhiên (trực tiếp) cập nhật trên biểu đồ d3, vì toàn bộ mô hình nhập / cập nhật / thoát làm cho nó đơn giản, một khi bạn có được nó.

datummặt khác, dường như tôi phù hợp hơn cho các biểu diễn tĩnh. Trong ví dụ dưới đây, ví dụ tôi có thể đạt được kết quả tương tự vòng lặp của mình trên mảng ban đầu và truy cập dữ liệu theo chỉ mục như vậy:

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

Dùng thử tại đây: https://jsfiddle.net/gleezer/e4m6j2d8/6/

Một lần nữa, tôi nghĩ rằng cách này dễ nắm bắt hơn khi bạn không phải chịu gánh nặng tinh thần đến từ mẫu nhập / cập nhật / thoát, nhưng ngay khi bạn cần cập nhật hoặc thay đổi lựa chọn, bạn chắc chắn sẽ tốt hơn khi dùng đến .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>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.