मेरे पास यह dc.js डेटाटेबल है जिसमें केवल दो कॉलम हैं, जिनमें से एक संख्या है। और मुझे उसी संख्या के साथ एक तीसरा कॉलम जोड़ने की जरूरत है, लेकिन कुल पर प्रतिशत के रूप में व्यक्त किया गया है:

VENDOR   SCORE      PERCENT
-------  -----      -------
Charles  5          50.0 %  
Sarah    4          40.0 %
John     1          10.0 %

यदि तालिका स्थिर थी, तो मैं केवल प्रतिशत की गणना करूंगा और उन्हें क्रॉसफ़िल्टर में पास करने से पहले डेटा सरणी में जोड़ूंगा:

let sum = data.reduce((accum, d) => accum + d.score, 0);
data.forEach(d => { d.percent = 100 * d.score / sum; });

लेकिन डेटा को फ़िल्टर किया जा सकता है (dc.js चार्ट और selectMenus का उपयोग करके), उदाहरण के लिए उपयोगकर्ता केवल महिला विक्रेताओं को प्रदर्शित करना चुन सकता है, और फिर तालिका केवल सारा को दिखाएगी... लेकिन उसके पुराने प्रतिशत के साथ, पुनर्गणना के बजाय 40% इसे 100% तक।

क्या कोई तरीका है जिससे मैं इसके आसपास काम कर सकूं? मुझे लगता है कि प्रतिशत की स्वचालित रूप से गणना करने का कोई तरीका नहीं है। लेकिन हो सकता है कि मैं कुछ ईवेंट में श्रोता जोड़ सकता हूं जो डेटा फ़िल्टर होने के बाद ट्रिगर होता है, लेकिन इससे पहले कि dc.js तालिका को फिर से तैयार करता है?


वैसे, अगर इससे कोई फर्क पड़ता है... चीजों को बदतर बनाने के लिए, मैं सीधे डेटा आयाम के साथ काम नहीं कर रहा हूं, इसके बजाय मैं टेबल पर एक नकली समूह पास कर रहा हूं (यहां से उधार लिया गया कोड):

function filteredGroup(originalGroup, filterFunction) {
  return {
    all: () => originalGroup.all().filter(filterFunction),
    top: n => originalGroup.top(Infinity).filter(filterFunction).slice(0, n),
    bottom: n => originalGroup.top(Infinity).filter(filterFunction).slice(-n).reverse()
  };
}

let ndx = crossfilter(data);
let dim = ndx.dimension(d => d.vendor);
let grp = filteredGroup(dim.group().reduceCount(), d => d.value > 0);

dc.dataTable('#id')
  .dimension(grp)
  .group(d => d.someOtherField)
  .showGroups(true)
  .columns([d => d.vendor, d => d.score])
  ...

(मेरी वास्तविक डेटा सरणी में चार्ल्स के लिए 5 प्रविष्टियां, सारा के लिए 4 और जॉन के लिए 1 प्रविष्टियां होंगी। प्रत्येक में अधिक जानकारी शामिल है, जैसे दिनांक और समय, जिसका उपयोग चयनमेनस में फ़िल्टरिंग की अनुमति देने के लिए किया जाता है। लेकिन मुझे टेबल पर समेकित डेटा चाहिए। इसलिए मैं आयाम के बजाय समूह का उपयोग कर रहा हूं।)

1
AJPerez 18 अक्टूबर 2018, 20:07

1 उत्तर

सबसे बढ़िया उत्तर

इसे करना वास्तव में बहुत आसान है। मैंने परिप्रेक्ष्य खो दिया था, एक "समूह" कोई रहस्यमय चीज नहीं है जो जादुई रूप से काम करती है। यह केवल 3 कार्यों के साथ एक वस्तु है: all, जो सभी डेटा के साथ एक सरणी देता है, और top और bottom, जो ऐसा ही करते हैं लेकिन केवल पहले N या अंतिम N तत्व लौटाते हैं . और जैसा कि गॉर्डन ने अपनी टिप्पणी में बताया, इन कार्यों को हर बार एक टेबल प्रदर्शित होने पर बुलाया जाता है।

इसलिए, मुझे नकली समूह परिभाषा के अंदर अपने प्रतिशत की गणना करने की आवश्यकता है:

function filteredGroup(originalGroup, filterFunction) {
  return {
    all: () => calc(originalGroup.all().filter(filterFunction)),
    top: n => calc(originalGroup.top(Infinity).filter(filterFunction)).slice(0, n),
    bottom: n => calc(originalGroup.top(Infinity).filter(filterFunction)).slice(-n).reverse()
  };
}

function calc(data) {
  let sum = data.reduce((accum, d) => accum + d.score, 0);
  data.forEach(d => { d.percent = 100 * d.score / sum; });
  return data;
}
2
AJPerez 22 अक्टूबर 2018, 13:37