อะไรคือความแตกต่างของข้อมูล D3 กับข้อมูล?


199

ใครช่วยอธิบายความแตกต่างระหว่าง datum () และ data () ใน D3.js ได้ไหม? ฉันเห็นทั้งการใช้งานและฉันไม่แน่ใจว่าทำไมคุณควรเลือกอันใดอันหนึ่ง

คำตอบ:


164

ฉันพบคำตอบที่ถูกต้องจากไมค์เอง:

D3 - วิธีจัดการกับโครงสร้างข้อมูล JSON?

หากคุณต้องการผูกข้อมูลของคุณกับองค์ประกอบ SVG เดียวให้ใช้

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

หรือ

(...).datum(data)

หากคุณต้องการผูกข้อมูลของคุณเข้ากับองค์ประกอบ SVG หลายรายการ

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

.....


ขอบคุณสำหรับสิ่งนี้! ความจริงที่ว่าคุณใส่ data ([data]) การส่งผ่านและอาเรย์ช่วยให้ฉันตระหนักถึงข้อผิดพลาดที่ฉันไม่สามารถหาได้ในสัปดาห์ที่ผ่านมา! ขอบคุณมาก ... สิ่งที่โง่เช่นนั้นผิดเสมอ
Adam

22
data () ดำเนินการเข้าร่วม datum () ไม่
s3-4v

เพียงจำไว้ว่าในกรณีที่มีองค์ประกอบข้อมูลอาเรย์มากกว่าองค์ประกอบ SVG เมื่อรวมข้อมูลเข้าด้วยenter()กัน d3 จะผูกองค์ประกอบส่วนที่เหลือกับองค์ประกอบ SVG ที่สร้างขึ้นใหม่
aslantorret

49

หลังจากตรวจสอบเล็กน้อยฉันพบว่าคำตอบที่นี่บน SO นั้นไม่สมบูรณ์เนื่องจากครอบคลุมเฉพาะกรณีเมื่อคุณเรียกใช้selection.dataและselection.datumมีdataพารามิเตอร์อินพุต แม้ว่าในสถานการณ์นั้นทั้งสองจะทำงานต่างกันหากการเลือกเป็นองค์ประกอบเดียวกับเมื่อมีหลายองค์ประกอบ ยิ่งไปกว่านั้นวิธีการทั้งสองนี้ยังสามารถเรียกใช้โดยไม่มีข้อโต้แย้งอินพุตเพื่อสอบถามข้อมูล / ข้อมูลที่ถูกผูกไว้ในการเลือกซึ่งในกรณีนี้พวกเขาจะทำงานแตกต่างกันอีกครั้งและส่งคืนสิ่งต่าง ๆ

แก้ไข - ฉันโพสต์คำตอบโดยละเอียดเพิ่มเติมเล็กน้อยสำหรับคำถามนี้ที่นี่แต่โพสต์ด้านล่างค่อนข้างจับประเด็นสำคัญทั้งหมดเกี่ยวกับสองวิธีและความแตกต่างจากกันและกัน

เมื่อขาย dataเป็นอาร์กิวเมนต์ป้อนเข้า

  • selection.data(data)จะพยายามที่จะดำเนินการข้อมูลร่วมระหว่างองค์ประกอบของdataอาร์เรย์ที่มีให้เลือกในการสร้างผลของenter(), exit()และupdate()เลือกที่คุณต่อมาสามารถทำงานบน ผลลัพธ์สุดท้ายของสิ่งนี้คือถ้าคุณส่งผ่านอาร์เรย์จะdata = [1,2,3]มีการพยายามเข้าร่วมแต่ละองค์ประกอบข้อมูล (เช่นข้อมูล) กับการเลือก องค์ประกอบของการเลือกแต่ละรายการจะมีองค์ประกอบ datum เดียวที่dataถูกผูกไว้กับมัน

  • selection.datum(data)ข้ามกระบวนการเข้าร่วมข้อมูลโดยสิ้นเชิง สิ่งนี้จะกำหนดdataองค์ประกอบทั้งหมดให้กับองค์ประกอบทั้งหมดในการเลือกโดยไม่แยกเป็นส่วน ๆ ในกรณีของการรวมข้อมูล ดังนั้นหากคุณต้องการที่จะผูกอาร์เรย์ทั้งหมดdata = [1, 2, 3]ทุกองค์ประกอบ DOM ในของคุณselectionแล้วselection.datum(data)จะประสบความสำเร็จนี้

คำเตือน:หลายคนเชื่อว่าselection.datum(data)จะเทียบเท่ากับselection.data([data])แต่นี้เป็นจริงเฉพาะในกรณี ที่มีองค์ประกอบเดียวselection หากselectionมีองค์ประกอบ DOM หลายรายการคุณselection.datum(data)จะผูกองค์ประกอบทั้งหมดdataกับทุกรายการในการเลือก ในทางตรงกันข้ามselection.data([data])จะผูกองค์ประกอบทั้งหมดdata เข้ากับองค์ประกอบแรกselectionเท่านั้น selection.dataซึ่งสอดคล้องกับข้อมูลที่เข้าร่วมการทำงานของ

เมื่อไม่ได้ระบุdataอาร์กิวเมนต์อินพุต

  • selection.data()จะใช้ datum ที่ถูกผูกไว้สำหรับแต่ละองค์ประกอบในการเลือกและรวมเข้าไปในอาร์เรย์ที่ส่งคืน ดังนั้นถ้าคุณselectionมี 3 องค์ประกอบ DOM กับข้อมูล"a", "b"และ"c"ผูกไว้กับแต่ละตามลำดับผลตอบแทนselection.data() ["a", "b", "c"]เป็นสิ่งสำคัญที่จะต้องทราบว่าหากselectionเป็นองค์ประกอบเดียวที่มี (ตามตัวอย่าง) ตัวเลขที่"a"ผูกไว้กับมันจากนั้นselection.data()จะกลับมา["a"]และไม่"a"เป็นไปตามที่บางคนคาด

  • selection.datum()ทำให้เหมาะสมสำหรับการเลือกเดียวตามที่กำหนดไว้เป็นการส่งคืนข้อมูลที่โยงกับองค์ประกอบแรกของการเลือก ดังนั้นในตัวอย่างข้างต้นด้วยการเลือกประกอบด้วยองค์ประกอบ DOM กับตัวเลขที่ถูกผูกไว้ของ"a", "b"และ"c", การกลับมาก็จะselection.datum()"a"

โปรดทราบว่าแม้ว่าจะselectionมีองค์ประกอบเดียวselection.datum()และselection.data()ส่งกลับค่าที่แตกต่างกัน อดีตส่งกลับ datum ที่ถูกผูกไว้สำหรับการเลือก ( "a"ในตัวอย่างด้านบน) ในขณะที่หลังส่งคืน datum ที่ถูกผูกไว้ภายในอาร์เรย์ ( ["a"]ในตัวอย่างด้านบน)

หวังว่าสิ่งนี้จะช่วยชี้แจงว่าselection.dataและselection.datum()แตกต่างจากกันอย่างไรเมื่อให้ข้อมูลเป็นอาร์กิวเมนต์อินพุตและเมื่อทำการสืบค้น datum ที่ถูกผูกไว้โดยไม่ระบุอาร์กิวเมนต์อินพุตใด ๆ

PS - วิธีที่ดีที่สุดที่จะเข้าใจวิธีการทำงานนี้คือการเริ่มต้นด้วยเอกสาร HTML ว่างเปล่าใน Chrome และจะเปิดคอนโซลและลองเพิ่มองค์ประกอบไม่กี่เอกสารและจากนั้นเริ่มมีผลผูกพันข้อมูลโดยใช้และselection.data selection.datumบางครั้งมันง่ายกว่าที่จะ "grok" บางอย่างโดยการทำมากกว่าการอ่าน


HamsterHuey ได้แสดงสิ่งนี้แล้ว แต่มันอาจเป็นเครื่องเตือนความทรงจำที่มีประโยชน์เพื่อเตือนว่า "datum" นั้นเป็นเอกพจน์และ "data" นั้นเป็นพหูพจน์ ดังนั้น. datum ใช้กับข้อมูลที่เกี่ยวข้องขององค์ประกอบเดียว
Visio Guy

42

นี่คือลิงค์ที่ดีบางส่วน:

ต่อหลัง:

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

เข้าร่วมอาร์เรย์ของข้อมูลที่ระบุด้วยการเลือกปัจจุบัน ค่าที่ระบุคืออาร์เรย์ของค่าข้อมูลเช่นอาร์เรย์ของตัวเลขหรือวัตถุหรือฟังก์ชันที่ส่งคืนอาร์เรย์ของค่า

...

# selection.datum([value])

รับหรือตั้งค่าข้อมูลที่ถูกผูกไว้สำหรับแต่ละองค์ประกอบที่เลือก ซึ่งแตกต่างจากวิธี selection.data วิธีนี้ไม่ได้คำนวณการเข้าร่วม (และไม่คำนวณการเข้าและออกจากการเลือก)


11
ให้คำนิยามเหล่านั้น - ฉันยังคงสับสนว่าทำไมคุณเคยจะต้อง / ต้องการที่จะใช้ตัวเลข ()
josephmisiti

อีกตัวอย่างหนึ่งที่อาจช่วยทำให้สิ่งที่ชัดเจน: ngokevin.com/blog/d3 หมายเหตุ: 1) คำจำกัดความของเควิน: "ข้อมูลคือข้อมูลที่เชื่อมโยงกับองค์ประกอบ" 2) สังเกตว่าในตัวอย่างของ Kevin เรา "รวม" ชุดข้อมูลกับ "data ()" ... แต่เรา "ใช้" ชุดย่อยโดยอ้างอิง "datum ()"
paulsm4

5

ฉันคิดว่าคำอธิบายของ HamsterHuey นั้นดีที่สุดแล้ว เพื่อขยายมันและให้การแสดงออกของความแตกต่างฉันสร้างเอกสารตัวอย่างที่แสดงให้เห็นในส่วนที่น้อยที่สุดของความแตกต่างระหว่างและdatadatum

คำตอบด้านล่างนี้เป็นความเห็นที่มากขึ้นจากการใช้วิธีการเหล่านี้ แต่ฉันยินดีที่จะแก้ไขหากฉันผิด

ตัวอย่างนี้สามารถเรียกใช้ด้านล่างหรือในซอนี้

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

ฉันคิดว่าdatumมันง่ายกว่าที่จะเข้าใจเนื่องจากมันไม่ได้เข้าร่วม แต่แน่นอนว่านี่หมายความว่ามันมีกรณีการใช้ที่แตกต่างกัน

สำหรับฉันความแตกต่างที่สำคัญอย่างหนึ่ง - ถึงแม้ว่าจะมีมากกว่านั้นก็คือความจริงที่dataเป็นเพียงวิธีธรรมชาติในการอัปเดต (สด) บนแผนภูมิ d3 เนื่องจากรูปแบบการป้อน / การอัปเดต / ออกทั้งหมดทำให้มันง่ายขึ้นเมื่อคุณได้รับ

datumในทางตรงกันข้ามดูเหมือนว่าฉันจะเหมาะสำหรับการเป็นตัวแทนคงที่ ในตัวอย่างด้านล่างตัวอย่างเช่นฉันสามารถบรรลุผลเดียวกันลูปของฉันในอาร์เรย์เดิมและเข้าถึงข้อมูลตามดัชนีดังนี้:

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

ลองที่นี่: https://jsfiddle.net/gleezer/e4m6j2d8/6/

อีกครั้งผมคิดว่านี่เป็นวิธีที่ง่ายต่อการเข้าใจที่คุณให้เป็นอิสระจากภาระทางจิตมาจากใส่ / ปรับปรุง / รูปแบบการออก .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>

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.