2016-10-28 95 views
3

新:我在我的解決方案中發佈的小提琴(https://jsfiddle.net/jnf84n7c/)。但是,當我嘗試在我的項目中實施這些策略時,我遇到了問題。當我點擊不是第一個圖的圖時,我收到一條錯誤消息。d3/dc.js - 如何在告訴crossfilter將數組中的元素作爲單獨記錄處理時創建堆疊條形圖?

Uncaught TypeError: a.group.all is not a function (error located in dc.min.js)

任何想法爲什麼它在小提琴中工作,但不適用於我的ruby-on-rails應用程序?

新代碼

var data = [ 
    {"key":"KEY-1","state":"MA","status":["A","R","C"],"items":["orange","meat","bread"],"date":"Y16"}, 
    {"key":"KEY-2","state":"MA","status":["A","O"],"items":["apple","bread"],"date":"Y15"}, 
    {"key":"KEY-3","state":"TX","status":["O"],"items":["bread"],"date":"Y16"}, 
    {"key":"KEY-4","state":"TN","status":["A","R"],"items":["apple","bread"],"date":"Y16"}, 
    {"key":"KEY-5","state":"TN","status":["A","O"],"items":["apple","orange"],"date":"Y15"}, 
    {"key":"KEY-6","state":"TN","status":[],"items":[],"date":"Y14"} 
]; 
var cf = crossfilter(data); 
var dates  = cf.dimension(function(d){ return d.date; }); 
var datesGroup = dates.group(); 
var states  = cf.dimension(function(d){ return d.state; }); 
var statesGroup = states.group(); 
var itemsDim = cf.dimension(function(d){ return d.items; }); 
var itemsGroup = itemsDim.groupAll().reduce(reduceAdd, reduceRemove, reduceInitial).value(); 
itemsGroup.all = myAllFunction; 
var states_items_group_apple = states.group().reduce(reduceAdd_apple, reduceRemove_apple, reduceInitial_items); 
var states_items_group_bread = states.group().reduce(reduceAdd_bread, reduceRemove_bread, reduceInitial_items); 
var states_items_group_orange = states.group().reduce(reduceAdd_orange, reduceRemove_orange, reduceInitial_items); 
var states_items_group_meat = states.group().reduce(reduceAdd_meat, reduceRemove_meat, reduceInitial_items); 
var itemsGroup1 = itemsDim.groupAll().reduce(reduceAdd1, reduceRemove1, reduceInitial).value(); 
var itemsGroup2 = itemsDim.groupAll().reduce(reduceAdd2, reduceRemove2, reduceInitial).value(); 
var itemsGroup3 = itemsDim.groupAll().reduce(reduceAdd3, reduceRemove3, reduceInitial).value(); 
itemsGroup1.all = myAllFunction; 
itemsGroup2.all = myAllFunction; 
itemsGroup3.all = myAllFunction; 
var status  = cf.dimension(function(d){ return d.status; }); 
var statusGroup1 = status.groupAll().reduce(reduceAdd_group1, reduceRemove_group1, reduceInitial_group).value(); 
var statusGroup2 = status.groupAll().reduce(reduceAdd_group2, reduceRemove_group2, reduceInitial_group).value(); 
var statusGroup3 = status.groupAll().reduce(reduceAdd_group3, reduceRemove_group3, reduceInitial_group).value(); 
var statusGroup4 = status.groupAll().reduce(reduceAdd_group4, reduceRemove_group4, reduceInitial_group).value(); 
statusGroup1.all = myAllFunction; 
statusGroup2.all = myAllFunction; 
statusGroup3.all = myAllFunction; 
statusGroup4.all = myAllFunction; 
var statusGroup = status.groupAll().reduce(reduceAdd_group, reduceRemove_group, reduceInitial_group).value(); 
statusGroup.all = myAllFunction; 
var row = dc.rowChart("#rowchart"); 
row.height(170) 
    .dimension(itemsDim) 
    .group(itemsGroup) 
    .ordering(function(d){return -d.value;}) 
    .renderLabel(true) 
    .ordinalColors(["#008600","#80FF80","#FF80FF","#860086"]) 
    .xAxis().ticks(3); 
row.filterHandler(myFilterFunction); 
var pie1 = dc.pieChart("#piechart1"); 
pie1.height(75).width(75) 
    .dimension(dates) 
    .group(datesGroup); 
var pie2 = dc.pieChart("#piechart2"); 
pie2.height(75).width(75) 
    .dimension(states) 
    .group(statesGroup); 
var pie3 = dc.pieChart("#piechart3"); 
pie3.height(75).width(75) 
    .dimension(status) 
    .group(statusGroup); 
pie3.filterHandler(myFilterFunction); 
var bar = dc.barChart("#barchart"); 
bar.width(500).height(200) 
    .dimension(states) 
    .group(states_items_group_bread, 'bread') 
    .stack(states_items_group_orange, 'orange') 
    .stack(states_items_group_apple, 'apple') 
    .stack(states_items_group_meat, 'meat') 
    .valueAccessor(function(p){ return p.value.count; }) 
    .renderHorizontalGridLines(true) 
    .renderLabel(true) 
    .legend(dc.legend().x(100).y(0).horizontal(1).itemHeight(13).gap(6).legendWidth(400).itemWidth(100)) 
    .gap(10) 
    .elasticX(true).elasticY(true) 
    .yAxisLabel("count") 
    .x(d3.scale.ordinal()) 
    .xUnits(dc.units.ordinal) 
    .margins({top:30,left:50,right:10,bottom:50});  
var bar2 = dc.barChart("#barchart2"); 
bar2.width(500).height(200) 
    .dimension(itemsDim) 
    .group(itemsGroup1,'MA') 
    .stack(itemsGroup2,'TN') 
    .stack(itemsGroup3,'TX') 
    .renderHorizontalGridLines(true) 
    .renderLabel(true) 
    .legend(dc.legend().x(60).y(0).horizontal(1).itemHeight(13).gap(6).legendWidth(400).itemWidth(60)) 
    .gap(10) 
    .yAxisLabel("count") 
    .x(d3.scale.ordinal()) 
    .xUnits(dc.units.ordinal) 
    .ordinalColors(["#008600","#80FF80","#FF80FF","#860086"]) 
    .margins({top:30,left:50,right:10,bottom:50}); 
bar2.filterHandler(myFilterFunction); 
var bar3 = dc.barChart("#barchart3"); 
bar3.width(500).height(200) 
    .dimension(status) 
    .group(statusGroup1,"bread") 
    .stack(statusGroup2,"apple") 
    .stack(statusGroup3,"orange") 
    .stack(statusGroup4,"meat") 
    .renderHorizontalGridLines(true) 
    .renderLabel(true) 
    .legend(dc.legend().x(60).y(0).horizontal(1).itemHeight(13).gap(6).legendWidth(400).itemWidth(60)) 
    .gap(10) 
    .yAxisLabel("count") 
    .x(d3.scale.ordinal()) 
    .xUnits(dc.units.ordinal) 
    .margins({top:30,left:50,right:10,bottom:50}); 
bar3.filterHandler(myFilterFunction); 
dc.renderAll(); 
function reduceAdd(p,v){ 
    if (v.items[0] === "") return p; 
    v.items.forEach(function(val,idx){ 
     p[val] = (p[val] || 0) + 1; 
    }); 
    return p; 
} 
function reduceRemove(p,v){ 
    if (v.items[0] === "") return p; 
    v.items.forEach(function(val,idx){ 
     p[val] = (p[val] || 0) - 1; 
    }); 
    return p; 
} 
function reduceInitial(){ 
    return { 
     bread: 0, 
     apple: 0, 
     orange: 0, 
     meat: 0 
    }; 
} 
function reduceAdd1(p,v){ 
    if (v.items[0] === "") return p; 
    if (v.state === "MA"){ 
     v.items.forEach(function(val,idx){ 
      p.bread += (val === 'bread' ? 1 : 0); 
      p.apple += (val === 'apple' ? 1 : 0); 
      p.orange += (val === 'orange' ? 1 : 0); 
      p.meat += (val === 'meat' ? 1 : 0); 
     }); 
    } 
    return p; 
} 
function reduceRemove1(p,v){ 
    if (v.items[0] === "") return p; 
    if (v.state === "MA"){ 
     v.items.forEach(function(val,idx){ 
      p.bread -= (val === 'bread' ? 1 : 0); 
      p.apple -= (val === 'apple' ? 1 : 0); 
      p.orange -= (val === 'orange' ? 1 : 0); 
      p.meat -= (val === 'meat' ? 1 : 0); 
     }); 
    } 
    return p; 
} 
function reduceAdd2(p,v){ 
    if (v.items[0] === "") return p; 
    if (v.state === "TN"){ 
     v.items.forEach(function(val,idx){ 
      p.bread += (val === 'bread' ? 1 : 0); 
      p.apple += (val === 'apple' ? 1 : 0); 
      p.orange += (val === 'orange' ? 1 : 0); 
      p.meat += (val === 'meat' ? 1 : 0); 
     }); 
    } 
    return p; 
} 
function reduceRemove2(p,v){ 
    if (v.items[0] === "") return p; 
    if (v.state === "TN"){ 
     v.items.forEach(function(val,idx){ 
      p.bread -= (val === 'bread' ? 1 : 0); 
      p.apple -= (val === 'apple' ? 1 : 0); 
      p.orange -= (val === 'orange' ? 1 : 0); 
      p.meat -= (val === 'meat' ? 1 : 0); 
     }); 
    } 
    return p; 
} 
function reduceAdd3(p,v){ 
    if (v.items[0] === "") return p; 
    if (v.state === "TX"){ 
     v.items.forEach(function(val,idx){ 
      p.bread += (val === 'bread' ? 1 : 0); 
      p.apple += (val === 'apple' ? 1 : 0); 
      p.orange += (val === 'orange' ? 1 : 0); 
      p.meat += (val === 'meat' ? 1 : 0); 
     }); 
    } 
    return p; 
} 
function reduceRemove3(p,v){ 
    if (v.items[0] === "") return p; 
    if (v.state === "TX"){ 
     v.items.forEach(function(val,idx){ 
      p.bread -= (val === 'bread' ? 1 : 0); 
      p.apple -= (val === 'apple' ? 1 : 0); 
      p.orange -= (val === 'orange' ? 1 : 0); 
      p.meat -= (val === 'meat' ? 1 : 0); 
     }); 
    } 
    return p; 
} 
function reduceAdd_apple(p,v){ 
    if (v.items[0] === "") return p; 
    p.state = v.state; 
    v.items.forEach(function(val,idx){ 
     p.count += (val === 'apple' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceRemove_apple(p,v){ 
    if (v.items[0] === "") return p; 
    p.state = v.state; 
    v.items.forEach(function(val,idx){ 
     p.count -= (val === 'apple' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceAdd_bread(p,v){ 
    if (v.items[0] === "") return p; 
    p.state = v.state; 
    v.items.forEach(function(val,idx){ 
     p.count += (val === 'bread' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceRemove_bread(p,v){ 
    if (v.items[0] === "") return p; 
    p.state = v.state; 
    v.items.forEach(function(val,idx){ 
     p.count -= (val === 'bread' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceAdd_orange(p,v){ 
    if (v.items[0] === "") return p; 
    p.state = v.state; 
    v.items.forEach(function(val,idx){ 
     p.count += (val === 'orange' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceRemove_orange(p,v){ 
    if (v.items[0] === "") return p; 
    p.state = v.state; 
    v.items.forEach(function(val,idx){ 
     p.count -= (val === 'orange' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceAdd_meat(p,v){ 
    if (v.items[0] === "") return p; 
    p.state = v.state; 
    v.items.forEach(function(val,idx){ 
     p.count += (val === 'meat' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceRemove_meat(p,v){ 
    if (v.items[0] === "") return p; 
    p.state = v.state; 
    v.items.forEach(function(val,idx){ 
     p.count -= (val === 'meat' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceAdd_group1(p,v){ 
    if (v.items[0] === "") return p; 
    if (v.status[0] === "") return p; 
    v.items.forEach(function(val1,idx1){ 
     if (val1 === "bread"){ 
      v.status.forEach(function(val2,idx2){ 
       if(idx1 === idx2){ 
       p.A += (val2 === 'A' ? 1 : 0); 
       p.O += (val2 === 'O' ? 1 : 0); 
       p.C += (val2 === 'C' ? 1 : 0); 
       p.R += (val2 === 'R' ? 1 : 0); 
       } 
      }); 
     } 
    }); 
    return p; 
} 
function reduceRemove_group1(p,v){ 
    if (v.items[0] === "") return p; 
    if (v.status[0] === "") return p; 
    v.items.forEach(function(val1,idx1){ 
     if(val1 === "bread"){ 
      v.status.forEach(function(val2,idx2){ 
       if(idx1 === idx2){ 
       p.A -= (val2 === 'A' ? 1 : 0); 
       p.O -= (val2 === 'O' ? 1 : 0); 
       p.C -= (val2 === 'C' ? 1 : 0); 
       p.R -= (val2 === 'R' ? 1 : 0); 
       } 
      }); 
     } 
    }); 
    return p; 
} 
function reduceAdd_group2(p,v){ 
    if (v.items[0] === "") return p; 
    if (v.status[0] === "") return p; 
    v.items.forEach(function(val1,idx1){ 
     if(val1 === "apple"){ 
      v.status.forEach(function(val2,idx2){ 
       if(idx1 === idx2){ 
       p.A += (val2 === 'A' ? 1 : 0); 
       p.O += (val2 === 'O' ? 1 : 0); 
       p.C += (val2 === 'C' ? 1 : 0); 
       p.R += (val2 === 'R' ? 1 : 0); 
       } 
      }); 
     } 
    }); 
    return p; 
} 
function reduceRemove_group2(p,v){ 
    if (v.items[0] === "") return p; 
    if (v.status[0] === "") return p; 
    v.items.forEach(function(val1,idx1){ 
     if(val1 === "apple"){ 
      v.status.forEach(function(val2,idx2){ 
       if(idx1 === idx2){ 
       p.A -= (val2 === 'A' ? 1 : 0); 
       p.O -= (val2 === 'O' ? 1 : 0); 
       p.C -= (val2 === 'C' ? 1 : 0); 
       p.R -= (val2 === 'R' ? 1 : 0); 
       } 
      }); 
     } 
    }); 
    return p; 
} 
function reduceAdd_group3(p,v){ 
    if (v.items[0] === "") return p; 
    if (v.status[0] === "") return p; 
    v.items.forEach(function(val1,idx1){ 
     if(val1 === "orange"){ 
      v.status.forEach(function(val2,idx2){ 
       if(idx1 === idx2){ 
       p.A += (val2 === 'A' ? 1 : 0); 
       p.O += (val2 === 'O' ? 1 : 0); 
       p.C += (val2 === 'C' ? 1 : 0); 
       p.R += (val2 === 'R' ? 1 : 0); 
       } 
      }); 
     } 
    }); 
    return p; 
} 
function reduceRemove_group3(p,v){ 
    if (v.items[0] === "") return p; 
    if (v.status[0] === "") return p; 
    v.items.forEach(function(val1,idx1){ 
     if(val1 === "orange"){ 
      v.status.forEach(function(val2,idx2){ 
       if(idx1 === idx2){ 
       p.A -= (val2 === 'A' ? 1 : 0); 
       p.O -= (val2 === 'O' ? 1 : 0); 
       p.C -= (val2 === 'C' ? 1 : 0); 
       p.R -= (val2 === 'R' ? 1 : 0); 
       } 
      }); 
     } 
    }); 
    return p; 
} 
function reduceAdd_group4(p,v){ 
    if (v.items[0] === "") return p; 
    if (v.status[0] === "") return p; 
    v.items.forEach(function(val1,idx1){ 
     if(val1 === "meat"){ 
      v.status.forEach(function(val2,idx2){ 
       if(idx1 === idx2){ 
       p.A += (val2 === 'A' ? 1 : 0); 
       p.O += (val2 === 'O' ? 1 : 0); 
       p.C += (val2 === 'C' ? 1 : 0); 
       p.R += (val2 === 'R' ? 1 : 0); 
       } 
      }); 
     } 
    }); 
    return p; 
} 
function reduceRemove_group4(p,v){ 
    if (v.items[0] === "") return p; 
    if (v.status[0] === "") return p; 
    v.items.forEach(function(val1,idx1){ 
     if(val1 === "meat"){ 
      v.status.forEach(function(val2,idx2){ 
       if(idx1 === idx2){ 
       p.A -= (val2 === 'A' ? 1 : 0); 
       p.O -= (val2 === 'O' ? 1 : 0); 
       p.C -= (val2 === 'C' ? 1 : 0); 
       p.R -= (val2 === 'R' ? 1 : 0); 
       } 
      }); 
     } 
    }); 
    return p; 
} 
function reduceAdd_group(p,v){ 
    if (v.status[0] === "") return p; 
    v.status.forEach(function(val,idx){ 
     p[val] = (p[val] || 0) + 1; 
    }); 
    return p; 
} 
function reduceRemove_group(p,v){ 
    if (v.status[0] === "") return p; 
    v.status.forEach(function(val,idx){ 
     p[val] = (p[val] || 0) - 1; 
    }); 
    return p; 
} 
function reduceInitial_group(){ 
    return { 
     A: 0, 
     O: 0, 
     C: 0, 
     R: 0 
    }; 
} 
function reduceInitial_items(){ 
    return { 
     count: 0, 
     state: '' 
    }; 
} 
//filter function: 
function myFilterFunction(dimension,filters){ 
    dimension.filter(null); 
    if (filters.length === 0) 
     dimension.filter(null); 
    else 
     dimension.filterFunction(function(d){ 
      for(var i=0; i<d.length; i++){ 
       if (filters.indexOf(d[i]) >= 0) return true; 
      } 
      return false; 
     }); 
    return filters; 
} 
function myAllFunction(){ 
    var newObject = []; 
    for(var key in this){ 
     if(this.hasOwnProperty(key) && key != "all"){ 
      newObject.push({ 
       key: key, 
       value: this[key] 
      }); 
     } 
    } 
    return newObject; 
}; 

老問題: 對不起創建另一個問題。不幸的是,我無法評論其他帖子來問我的問題。類似於礦的兩個問題是: dc.js - how to group by unique idIs there a way to tell crossfilter to treat elements of array as separate records instead of treating whole array as single key?

我使用的代碼作爲後者解釋。但是,我希望能夠堆疊。由於您可以在jsfiddle中看到,底部條形圖不會列出x軸中的項目,堆疊不同的狀態計數。任何幫助將不勝感激。謝謝!

這裏是原來的小提琴:https://jsfiddle.net/7qwqcakr/1/

我幾乎與這個小提琴有它:https://jsfiddle.net/wq0ed5hr/ 但堆積條形圖是,即使傳說中他們爲不同的顏色都是一個顏色。我如何解決顏色問題?

固定顏色的問題:https://jsfiddle.net/rmc2zpr4/

現在唯一的問題是在我的解決方案和下面的註釋解釋了「計數問題」的交易。

這裏的更新代碼:

var data = [ 
    {"key":"KEY-1","state":"MA","items":["orange","meat","bread"],"date":"Y16"}, 
    {"key":"KEY-2","state":"MA","items":["apple","bread"],"date":"Y15"}, 
    {"key":"KEY-3","state":"TX","items":["bread"],"date":"Y16"}, 
    {"key":"KEY-4","state":"TN","items":["apple","bread"],"date":"Y16"}, 
    {"key":"KEY-5","state":"TN","items":["apple","orange"],"date":"Y15"}, 
    {"key":"KEY-6","state":"TN","items":[],"date":"Y14"} 
]; 
var cf = crossfilter(data); 
var dates  = cf.dimension(function(d){ return d.date; }); 
var datesGroup = dates.group().reduceCount(function(d){ return d.key; }); 
var states  = cf.dimension(function(d){ return d.state; }); 
var statesGroup = states.group().reduceCount(function(d){ return d.key; }); 
var itemsDim = cf.dimension(function(d){ return d.items; }); 
var itemsGroup = itemsDim.groupAll().reduce(reduceAdd, reduceRemove, reduceInitial).value(); 
itemsGroup.all = myAllFunction; 
var statesDim = cf.dimension(function(d){ return d.state; }); 
var states_items_group_apple = statesDim.group().reduce(reduceAdd_apple, reduceRemove_apple, reduceInitial_items); 
var states_items_group_bread = statesDim.group().reduce(reduceAdd_bread, reduceRemove_bread, reduceInitial_items); 
var states_items_group_orange = statesDim.group().reduce(reduceAdd_orange, reduceRemove_orange, reduceInitial_items); 
var states_items_group_meat = statesDim.group().reduce(reduceAdd_meat, reduceRemove_meat, reduceInitial_items); 
var items  = cf.dimension(function(d){ return d.items; }) 
var itemsGroup1 = items.groupAll().reduce(reduceAdd1, reduceRemove1, reduceInitial).value(); 
var itemsGroup2 = items.groupAll().reduce(reduceAdd2, reduceRemove2, reduceInitial).value(); 
var itemsGroup3 = items.groupAll().reduce(reduceAdd3, reduceRemove3, reduceInitial).value(); 
itemsGroup1.all = myAllFunction; 
itemsGroup2.all = myAllFunction; 
itemsGroup3.all = myAllFunction; 
var row = dc.rowChart("#rowchart"); 
row.height(170) 
    .dimension(itemsDim) 
    .group(itemsGroup) 
    .ordering(function(d){return -d.value;}) 
    .renderLabel(true) 
     .ordinalColors(["#008600","#80FF80","#FF80FF","#860086"]) 
    .xAxis().ticks(3); 
row.filterHandler(myFilterFunction); 
var pie1 = dc.pieChart("#piechart1"); 
pie1.height(75).width(75) 
    .dimension(dates) 
    .group(datesGroup); 
var pie2 = dc.pieChart("#piechart2"); 
pie2.height(75).width(75) 
    .dimension(states) 
    .group(statesGroup); 
var bar = dc.barChart("#barchart"); 
bar.width(500).height(200) 
    .dimension(statesDim) 
    .group(states_items_group_bread, 'bread') 
    .stack(states_items_group_orange, 'orange') 
    .stack(states_items_group_apple, 'apple') 
    .stack(states_items_group_meat, 'meat') 
    .valueAccessor(function(p){ return p.value.count; }) 
    .renderHorizontalGridLines(true) 
    .renderLabel(true) 
    .legend(dc.legend().x(100).y(0).horizontal(1).itemHeight(13).gap(6).legendWidth(400).itemWidth(100)) 
    .gap(10) 
    .elasticX(true).elasticY(true) 
    .yAxisLabel("count") 
    .x(d3.scale.ordinal()) 
    .xUnits(dc.units.ordinal) 
    .margins({top:30,left:50,right:10,bottom:50}); 
var bar2 = dc.barChart("#barchart2"); 
bar2.width(500).height(200) 
    .dimension(items) 
    .group(itemsGroup1,'MA') 
    .stack(itemsGroup2,'TN') 
    .stack(itemsGroup3,'TX') 
    .renderHorizontalGridLines(true) 
    .renderLabel(true) 
    .legend(dc.legend().x(60).y(0).horizontal(1).itemHeight(13).gap(6).legendWidth(400).itemWidth(60)) 
    .gap(10) 
    .yAxisLabel("count") 
    .x(d3.scale.ordinal()) 
    .xUnits(dc.units.ordinal) 
    .ordinalColors(["#008600","#80FF80","#FF80FF","#860086"]) 
    .margins({top:30,left:50,right:10,bottom:50}); 
bar2.filterHandler(myFilterFunction); 
dc.renderAll(); 
//reduce functions: 
function reduceAdd(p,v){ 
    if (v.items[0] === "") return p; 
    v.items.forEach(function(val,idx){ 
     p[val] = (p[val] || 0) + 1; 
    }); 
    return p; 
} 
function reduceRemove(p,v){ 
    if (v.items[0] === "") return p; 
    v.items.forEach(function(val,idx){ 
     p[val] = (p[val] || 0) - 1; 
    }); 
    return p; 
} 
function reduceInitial(){ 
    return { 
     bread: 0, 
     apple: 0, 
     orange: 0, 
     meat: 0 
    }; 
} 
function reduceAdd1(p,v){ 
    if (v.items[0] === "") return p; 
    if (v.state === "MA"){ 
     v.items.forEach(function(val,idx){ 
      p.bread += (val === 'bread' ? 1 : 0); 
      p.apple += (val === 'apple' ? 1 : 0); 
      p.orange += (val === 'orange' ? 1 : 0); 
      p.meat += (val === 'meat' ? 1 : 0); 
     }); 
    } 
    return p; 
} 
function reduceRemove1(p,v){ 
    if (v.items[0] === "") return p; 
    if (v.state === "MA"){ 
     v.items.forEach(function(val, idx){ 
      p.bread -= (val === 'bread' ? 1 : 0); 
      p.apple -= (val === 'apple' ? 1 : 0); 
      p.orange -= (val === 'orange' ? 1 : 0); 
      p.meat -= (val === 'meat' ? 1 : 0); 
     }); 
    } 
    return p; 
} 
function reduceAdd2(p,v){ 
    if (v.items[0] === "") return p; 
    if (v.state === "TN"){ 
     v.items.forEach(function(val,idx){ 
      p.bread += (val === 'bread' ? 1 : 0); 
      p.apple += (val === 'apple' ? 1 : 0); 
      p.orange += (val === 'orange' ? 1 : 0); 
      p.meat += (val === 'meat' ? 1 : 0); 
     }); 
    } 
    return p; 
} 
function reduceRemove2(p,v){ 
    if (v.items[0] === "") return p; 
    if (v.state === "TN"){ 
     v.items.forEach(function(val,idx){ 
      p.bread -= (val === 'bread' ? 1 : 0); 
      p.apple -= (val === 'apple' ? 1 : 0); 
      p.orange -= (val === 'orange' ? 1 : 0); 
      p.meat -= (val === 'meat' ? 1 : 0); 
     }); 
    } 
    return p; 
} 
function reduceAdd3(p,v){ 
    if (v.items[0] === "") return p; 
    if (v.state === "TX"){ 
     v.items.forEach(function(val,idx){ 
      p.bread += (val === 'bread' ? 1 : 0); 
      p.apple += (val === 'apple' ? 1 : 0); 
      p.orange += (val === 'orange' ? 1 : 0); 
      p.meat += (val === 'meat' ? 1 : 0); 
     }); 
    } 
    return p; 
} 
function reduceRemove3(p,v){ 
    if (v.items[0] === "") return p; 
    if (v.state === "TX"){ 
     v.items.forEach(function(val,idx){ 
      p.bread -= (val === 'bread' ? 1 : 0); 
      p.apple -= (val === 'apple' ? 1 : 0); 
      p.orange -= (val === 'orange' ? 1 : 0); 
      p.meat -= (val === 'meat' ? 1 : 0); 
     }); 
    } 
    return p; 
} 
function reduceAdd_apple(p,v){ 
    if (v.items[0] === "") return p; 
    p.state = v.state; 
    v.items.forEach(function(val,idx){ 
     p.count += (val === 'apple' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceRemove_apple(p,v){ 
    if (v.items[0] === "") return p; 
    p.state = v.state; 
    v.items.forEach(function(val,idx){ 
     p.count -= (val === 'apple' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceAdd_bread(p,v){ 
    if (v.items[0] === "") return p; 
    p.state = v.state; 
    v.items.forEach(function(val,idx){ 
     p.count += (val === 'bread' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceRemove_bread(p,v){ 
    if (v.items[0] === "") return p; 
    p.state = v.state; 
    v.items.forEach(function(val,idx){ 
     p.count -= (val === 'bread' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceAdd_orange(p,v){ 
    if (v.items[0] === "") return p; 
    p.state = v.state; 
    v.items.forEach(function(val,idx){ 
     p.count += (val === 'orange' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceRemove_orange(p,v){ 
    if (v.items[0] === "") return p; 
    p.state = v.state; 
    v.items.forEach(function(val,idx){ 
     p.count -= (val === 'orange' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceAdd_meat(p,v){ 
    if (v.items[0] === "") return p; 
    p.state = v.state; 
    v.items.forEach(function(val,idx){ 
     p.count += (val === 'meat' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceRemove_meat(p,v){ 
    if (v.items[0] === "") return p; 
    p.state = v.state; 
    v.items.forEach(function(val,idx){ 
     p.count -= (val === 'meat' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceInitial_items(){ 
    return { 
     count: 0, 
     state: '' 
    }; 
} 
function myFilterFunction(dimension,filters){ 
    dimension.filter(null); 
    if(filters.length === 0) 
     dimension.filter(null); 
    else 
     dimension.filterFunction(function(d){ 
      for(var i=0; i<d.length; i++){ 
       if(filters.indexOf(d[i]) >= 0) return true; 
      } 
      return false; 
     }); 
    return filters; 
} 
function myAllFunction(){ 
    var newObject = []; 
    for(var key in this){ 
     if(this.hasOwnProperty(key) && key != "all"){ 
      newObject.push({ 
       key: key, 
       value: this[key] 
      }); 
     } 
    } 
    return newObject; 
}; 
+0

我創建了一個新的小提琴,使用我使用的庫版本,並且顏色問題得到了修復。這裏是小提琴:https://jsfiddle.net/rmc2zpr4/我寧願計數問題得到解決,但我主要只是很高興堆疊部分工作。 – Casey

回答

1

你需要做的第一件事是升級到:

  • dc.js 2.0 beta版
  • Crossfilter 1.4.0-β。 06(Crossfilter現在居住在這裏:https://github.com/crossfilter/crossfilter
  • Reductio(推薦),以便您不必手動構建自定義組gs - 這不是嚴格必要的,但分組是很多問題的根源,所以我建議使用ReductioUniverse來利用以前來過的人的工作。

接下來,所有這些新的善良,我們可以簡化一噸。下面是使用這些庫的新功能的更新小提琴:https://jsfiddle.net/ff8ox8vq/

我會在下面的完整代碼示例中詳細介紹它們。

var data = [ 
    {"key":"KEY-1","state":"MA", "items":["orange", "meat", "bread"], "date":"Y16"}, 
    {"key":"KEY-2","state":"MA", "items":["apple", "bread"], "date":"Y15"}, 
    {"key":"KEY-3","state":"TX", "items":["bread"], "date":"Y16"}, 
    {"key":"KEY-4","state":"TN", "items":["apple", "bread"], "date":"Y16"}, 
    {"key":"KEY-5","state":"TN", "items":["apple", "orange"], "date":"Y15"}, 
    {"key":"KEY-6","state":"TN", "items": [], "date":"Y14"} 
]; 

var cf = crossfilter(data); 

以上沒有變化。

//dimensions and groups: 
var dates  = cf.dimension(function(d){ return d.date; }); 
var datesGroup = dates.group(); 
var states  = cf.dimension(function(d){ return d.state; }); 
var statesGroup = states.group() 

.reduceCount是組的默認設置。在新組上調用它並不會執行任何操作。 reduceCount也不採用任何參數(與reduceSum不同)。所以我們只是擺脫它。

var itemsDim = cf.dimension(function(d){ return d.items; }, true); 
var itemsGroup = itemsDim.group(); 

這就是它開始變得有趣的地方。 Crossfilter 1.4.0支持維度調用中的「數組維度」標誌。如果我們將其設置爲true,Crossfilter知道items是一個數組,並且它將很好地處理它的處理方式。您不再需要重寫.all方法或類似的東西。它在內部處理。

var addValueGroup = function(reducer, key) { 
    reducer 
    .value(key) 
    .filter(function(d) { return d.items.indexOf(key) !== -1; }) 
    .count(true) 
} 

將項目特定計數添加到狀態組的實用程序功能。

// Reductio nest to break down states by item 
var reducer = reductio().count(true) 
addValueGroup(reducer, "orange") 
addValueGroup(reducer, "meat") 
addValueGroup(reducer, "bread") 
addValueGroup(reducer, "apple") 

reducer(statesGroup); 

配置statesGroup的分組。 Reductio只是建立自定義的減少功能。這裏發生的是我們維護一個狀態中所有記錄的頂級計數,然後我們爲每種類型的項目創建過濾計數。運行後,請執行console.log(statesGroup.all())以查看生成的組的結構。

//graphs: 
var row = dc.rowChart("#rowchart"); 
row 
    .renderLabel(true) 
    .height(200) 
    .dimension(itemsDim) 
    .group(itemsGroup) 
    .ordering(function(d){return -d.value;}) 
    .xAxis().ticks(3); 

var pie1 = dc.pieChart("#piechart1"); 
pie1 
    .height(75) 
    .width(75) 
    .dimension(dates) 
    .group(datesGroup); 

沒有變化。

var pie2 = dc.pieChart("#piechart2"); 
pie2 
    .height(75) 
    .width(75) 
    .dimension(states) 
    .group(statesGroup) 
    .valueAccessor(function(d) { return d.value.count; }); 

我們歸謬法減速變組的結構有點,所以我們需要一個valueAccessor

var bar = dc.barChart("#barchart"); 
bar.width(500).height(200) 
    .dimension(states) 
    .group(statesGroup, 'orange', sel_stack('orange')) 
    .stack(statesGroup, 'meat', sel_stack('meat')) 
    .stack(statesGroup, 'bread', sel_stack('bread')) 
    .stack(statesGroup, 'apple', sel_stack('apple')) 
    .renderHorizontalGridLines(true) 
    .renderLabel(true) 
    .legend(dc.legend()) 
    .gap(10) 
    .yAxisLabel("count") 
    .x(d3.scale.ordinal()) 
    .xUnits(dc.units.ordinal); 

只是沒有花哨的自定義過濾器功能或任何東西的作品。 dc.js和Crossfilter知道該怎麼做。不幸的是,在dc.js中似乎存在一個錯誤,使用序號疊加的條形圖,所以你必須在渲染之後正確地爲條形變色:-(也許戈登會在這裏提示一下。

dc.renderAll(); 

function sel_stack(i) { 
    return function(d) { 
     return d.value[i] ? d.value[i].count : 0; 
    }; 
} 

輕微變化,由於更新後的組結構,並在案件一點點安全你MIS型項目的關鍵之一。

+0

幾乎在那裏。我檢查了你的小提琴。當我在行圖中選擇「麪包」時,條形圖應更新爲僅包含「麪包」計數。它不是。我們如何更新代碼以進行此更改? – Casey

+0

爲了進一步解釋我的意思......我們的兩個例子似乎都顯示了包含所選項目的條目的項目總數。例如,當選擇「蘋果」時,「MA」顯示2 - 1蘋果,1麪包的數量(您可以突出顯示圖例以確定這些) - 而'TN'顯示4 - 1橙色的計數, 1個麪包,2個蘋果。例如,如何解決這個問題只顯示「apple」的計數? – Casey

+1

在dc.js中,當您單擊某一行時,表示「限制顯示在此欄中的記錄」。在這種情況下,它限制爲包含「麪包」的記錄,但由於每個記錄包含多個項目,其中一些記錄也包含蘋果。只顯示麪包實際上是不正確的,是嗎? –

0

我固定的彩色堆棧問題,計數問題我希望如何我正在使用D3.js verison 2.5.5,crossfilter.js 1.3.11版和dc.js和dc.css版本2.1.0 dev。https://jsfiddle.net/jnf84n7c/

var data = [ 
    {"key":"KEY-1","state":"MA", "status":["A","R","C"], "items":["orange", "meat", "bread"], "date":"Y16"}, 
    {"key":"KEY-2","state":"MA", "status":["A","O"], "items":["apple", "bread"], "date":"Y15"}, 
    {"key":"KEY-3","state":"TX", "status":["O"], "items":["bread"], "date":"Y16"}, 
    {"key":"KEY-4","state":"TN", "status":["A","R"], "items":["apple", "bread"], "date":"Y16"}, 
    {"key":"KEY-5","state":"TN", "status":["A","O"], "items":["apple", "orange"], "date":"Y15"}, 
    {"key":"KEY-6","state":"TN", "status":[], "items": [], "date":"Y14"} 
]; 

var cf = crossfilter(data); 

//dimensions and groups: 
var dates  = cf.dimension(function(d){ return d.date; }); 
var datesGroup = dates.group();//.reduceCount(function(d){ return d.key; }); 
var states  = cf.dimension(function(d){ return d.state; }); 
var statesGroup = states.group();//.reduceCount(function(d){ return d.key; }); 
var itemsDim = cf.dimension(function(d){ return d.items; }); 
var itemsGroup = itemsDim.groupAll().reduce(reduceAdd, reduceRemove, reduceInitial).value(); 
itemsGroup.all = myAllFunction; 
var states_items_group_apple = states.group().reduce(reduceAdd_apple, reduceRemove_apple, reduceInitial_items); 
var states_items_group_bread = states.group().reduce(reduceAdd_bread, reduceRemove_bread, reduceInitial_items); 
var states_items_group_orange = states.group().reduce(reduceAdd_orange, reduceRemove_orange, reduceInitial_items); 
var states_items_group_meat = states.group().reduce(reduceAdd_meat, reduceRemove_meat, reduceInitial_items); 
var itemsGroup1 = itemsDim.groupAll().reduce(reduceAdd1, reduceRemove1, reduceInitial).value(); 
var itemsGroup2 = itemsDim.groupAll().reduce(reduceAdd2, reduceRemove2, reduceInitial).value(); 
var itemsGroup3 = itemsDim.groupAll().reduce(reduceAdd3, reduceRemove3, reduceInitial).value(); 
itemsGroup1.all = myAllFunction; 
itemsGroup2.all = myAllFunction; 
itemsGroup3.all = myAllFunction; 
var status  = cf.dimension(function(d){ return d.status; }); 
var statusGroup1 = status.groupAll().reduce(reduceAdd_group1, reduceRemove_group1, reduceInitial_group).value(); 
var statusGroup2 = status.groupAll().reduce(reduceAdd_group2, reduceRemove_group2, reduceInitial_group).value(); 
var statusGroup3 = status.groupAll().reduce(reduceAdd_group3, reduceRemove_group3, reduceInitial_group).value(); 
var statusGroup4 = status.groupAll().reduce(reduceAdd_group4, reduceRemove_group4, reduceInitial_group).value(); 
statusGroup1.all = myAllFunction; 
statusGroup2.all = myAllFunction; 
statusGroup3.all = myAllFunction; 
statusGroup4.all = myAllFunction; 
var statusGroup = status.groupAll().reduce(reduceAdd_group, reduceRemove_group, reduceInitial_group).value(); 
statusGroup.all = myAllFunction; 

//graphs: 
var row = dc.rowChart("#rowchart"); 
row.height(170) 
    .dimension(itemsDim) 
    .group(itemsGroup) 
    .ordering(function(d){return -d.value;}) 
    .renderLabel(true) 
     .ordinalColors(["#008600", "#80FF80", "#FF80FF", "#860086"]) 
    .xAxis().ticks(3); 
row.filterHandler(myFilterFunction); 

var pie1 = dc.pieChart("#piechart1"); 
pie1.height(75).width(75) 
    .dimension(dates) 
    .group(datesGroup); 

var pie2 = dc.pieChart("#piechart2"); 
pie2.height(75).width(75) 
    .dimension(states) 
    .group(statesGroup); 

var pie3 = dc.pieChart("#piechart3"); 
pie3.height(75).width(75) 
    .dimension(status) 
    .group(statusGroup); 
pie3.filterHandler(myFilterFunction); 

var bar = dc.barChart("#barchart"); 
bar.width(500).height(200) 
    .dimension(states) 
    .group(states_items_group_bread, 'bread') 
    .stack(states_items_group_orange, 'orange') 
    .stack(states_items_group_apple, 'apple') 
    .stack(states_items_group_meat, 'meat') 
    .valueAccessor(function(p){ return p.value.count; }) 
    .renderHorizontalGridLines(true) 
    .renderLabel(true) 
    .legend(dc.legend().x(100).y(0).horizontal(1).itemHeight(13).gap(6).legendWidth(400).itemWidth(100)) 
    .gap(10) 
    .elasticX(true).elasticY(true) 
    .yAxisLabel("count") 
    .x(d3.scale.ordinal()) 
    .xUnits(dc.units.ordinal) 
    .margins({top:30, left:50, right:10, bottom:50}); 
//bar.filterHandler(myFilterFunction); 
//bar.on("renderlet", function(_chart){ 
// _chart.selectAll("rect.bar").on("click", _chart.onClick); 
//}); 

var bar2 = dc.barChart("#barchart2"); 
bar2.width(500).height(200) 
    .dimension(itemsDim) 
    .group(itemsGroup1, 'MA') 
    .stack(itemsGroup2, 'TN') 
    .stack(itemsGroup3, 'TX') 
    .renderHorizontalGridLines(true) 
    .renderLabel(true) 
    .legend(dc.legend().x(60).y(0).horizontal(1).itemHeight(13).gap(6).legendWidth(400).itemWidth(60)) 
    .gap(10) 
    .yAxisLabel("count") 
    .x(d3.scale.ordinal()) 
    .xUnits(dc.units.ordinal) 
    .ordinalColors(["#008600", "#80FF80", "#FF80FF", "#860086"]) 
    .margins({top:30, left:50, right:10, bottom:50}); 
bar2.filterHandler(myFilterFunction); 

var bar3 = dc.barChart("#barchart3"); 
bar3.width(500).height(200) 
    .dimension(status) 
    .group(statusGroup1, "bread") 
    .stack(statusGroup2, "apple") 
    .stack(statusGroup3, "orange") 
    .stack(statusGroup4, "meat") 
    .renderHorizontalGridLines(true) 
    .renderLabel(true) 
    .legend(dc.legend().x(60).y(0).horizontal(1).itemHeight(13).gap(6).legendWidth(400).itemWidth(60)) 
    .gap(10) 
    .yAxisLabel("count") 
    .x(d3.scale.ordinal()) 
    .xUnits(dc.units.ordinal) 
// .ordinalColors(["#008600", "#80FF80", "#FF80FF", "#860086"]) 
    .margins({top:30, left:50, right:10, bottom:50}); 
bar3.filterHandler(myFilterFunction); 

dc.renderAll(); // render graphs 

//reduce functions: 
function reduceAdd(p, v) { 
    if (v.items[0] === "") return p; // skip empty values 
    v.items.forEach (function(val, idx) { 
     p[val] = (p[val] || 0) + 1; //increment counts 
    }); 
    return p; 
} 
function reduceRemove(p, v) { 
    if (v.items[0] === "") return p; // skip empty values 
    v.items.forEach (function(val, idx) { 
     p[val] = (p[val] || 0) - 1; //decrement counts 
    }); 
    return p; 
} 
function reduceInitial() { 
    return { 
     bread: 0, 
     apple: 0, 
     orange: 0, 
     meat: 0 
    }; 
} 
function reduceAdd1(p, v) { 
    if (v.items[0] === "") return p; // skip empty values 
    if (v.state === "MA"){ 
     v.items.forEach (function(val, idx) { 
      p.bread += (val === 'bread' ? 1 : 0); 
      p.apple += (val === 'apple' ? 1 : 0); 
      p.orange += (val === 'orange' ? 1 : 0); 
      p.meat += (val === 'meat' ? 1 : 0); 
     });  
    } 
    return p; 
} 
function reduceRemove1(p, v) { 
    if (v.items[0] === "") return p; // skip empty values 
    if (v.state === "MA"){ 
     v.items.forEach (function(val, idx) { 
      p.bread -= (val === 'bread' ? 1 : 0); 
      p.apple -= (val === 'apple' ? 1 : 0); 
      p.orange -= (val === 'orange' ? 1 : 0); 
      p.meat -= (val === 'meat' ? 1 : 0); 
     });  
    } 
    return p; 
} 
function reduceAdd2(p, v) { 
    if (v.items[0] === "") return p; // skip empty values 
    if (v.state === "TN"){ 
     v.items.forEach (function(val, idx) { 
      p.bread += (val === 'bread' ? 1 : 0); 
      p.apple += (val === 'apple' ? 1 : 0); 
      p.orange += (val === 'orange' ? 1 : 0); 
      p.meat += (val === 'meat' ? 1 : 0); 
     });  
    } 
    return p; 
} 
function reduceRemove2(p, v) { 
    if (v.items[0] === "") return p; // skip empty values 
    if (v.state === "TN"){ 
     v.items.forEach (function(val, idx) { 
      p.bread -= (val === 'bread' ? 1 : 0); 
      p.apple -= (val === 'apple' ? 1 : 0); 
      p.orange -= (val === 'orange' ? 1 : 0); 
      p.meat -= (val === 'meat' ? 1 : 0); 
     });  
    } 
    return p; 
} 
function reduceAdd3(p, v) { 
    if (v.items[0] === "") return p; // skip empty values 
    if (v.state === "TX"){ 
     v.items.forEach (function(val, idx) { 
      p.bread += (val === 'bread' ? 1 : 0); 
      p.apple += (val === 'apple' ? 1 : 0); 
      p.orange += (val === 'orange' ? 1 : 0); 
      p.meat += (val === 'meat' ? 1 : 0); 
     });  
    } 
    return p; 
} 
function reduceRemove3(p, v) { 
    if (v.items[0] === "") return p; // skip empty values 
    if (v.state === "TX"){ 
     v.items.forEach (function(val, idx) { 
      p.bread -= (val === 'bread' ? 1 : 0); 
      p.apple -= (val === 'apple' ? 1 : 0); 
      p.orange -= (val === 'orange' ? 1 : 0); 
      p.meat -= (val === 'meat' ? 1 : 0); 
     });  
    } 
    return p; 
} 
function reduceAdd_apple(p, v){ 
    if (v.items[0] === "") return p; // skip empty values 
    p.state = v.state; 
    v.items.forEach(function(val, idx){ 
     p.count += (val === 'apple' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceRemove_apple(p, v){ 
    if (v.items[0] === "") return p; // skip empty values 
    p.state = v.state; 
    v.items.forEach(function(val, idx){ 
     p.count -= (val === 'apple' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceAdd_bread(p, v){ 
    if (v.items[0] === "") return p; // skip empty values 
    p.state = v.state; 
    v.items.forEach(function(val, idx){ 
     p.count += (val === 'bread' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceRemove_bread(p, v){ 
    if (v.items[0] === "") return p; // skip empty values 
    p.state = v.state; 
    v.items.forEach(function(val, idx){ 
     p.count -= (val === 'bread' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceAdd_orange(p, v){ 
    if (v.items[0] === "") return p; // skip empty values 
    p.state = v.state; 
    v.items.forEach(function(val, idx){ 
     p.count += (val === 'orange' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceRemove_orange(p, v){ 
    if (v.items[0] === "") return p; // skip empty values 
    p.state = v.state; 
    v.items.forEach(function(val, idx){ 
     p.count -= (val === 'orange' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceAdd_meat(p, v){ 
    if (v.items[0] === "") return p; // skip empty values 
    p.state = v.state; 
    v.items.forEach(function(val, idx){ 
     p.count += (val === 'meat' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceRemove_meat(p, v){ 
    if (v.items[0] === "") return p; // skip empty values 
    p.state = v.state; 
    v.items.forEach(function(val, idx){ 
     p.count -= (val === 'meat' ? 1 : 0); 
    }); 
    return p; 
} 
function reduceAdd_group1(p, v) { 
    if (v.items[0] === "") return p; // skip empty values 
    if (v.status[0] === "") return p; // skip empty values 
    v.items.forEach(function(val1, idx1){ 
     if (val1 === "bread"){ 
      v.status.forEach (function(val2, idx2) { 
       if (idx1 === idx2) { 
       p.A += (val2 === 'A' ? 1 : 0); 
       p.O += (val2 === 'O' ? 1 : 0); 
       p.C += (val2 === 'C' ? 1 : 0); 
       p.R += (val2 === 'R' ? 1 : 0); 
       } 
      });  
     } 
    }); 
    return p; 
} 
function reduceRemove_group1(p, v) { 
    if (v.items[0] === "") return p; // skip empty values 
    if (v.status[0] === "") return p; // skip empty values 
    v.items.forEach(function(val1, idx1){ 
     if (val1 === "bread"){ 
      v.status.forEach (function(val2, idx2) { 
       if (idx1 === idx2) { 
       p.A -= (val2 === 'A' ? 1 : 0); 
       p.O -= (val2 === 'O' ? 1 : 0); 
       p.C -= (val2 === 'C' ? 1 : 0); 
       p.R -= (val2 === 'R' ? 1 : 0); 
       } 
      });  
     } 
    }); 
    return p; 
} 
function reduceAdd_group2(p, v) { 
    if (v.items[0] === "") return p; // skip empty values 
    if (v.status[0] === "") return p; // skip empty values 
    v.items.forEach(function(val1, idx1){ 
     if (val1 === "apple"){ 
      v.status.forEach (function(val2, idx2) { 
       if (idx1 === idx2) { 
       p.A += (val2 === 'A' ? 1 : 0); 
       p.O += (val2 === 'O' ? 1 : 0); 
       p.C += (val2 === 'C' ? 1 : 0); 
       p.R += (val2 === 'R' ? 1 : 0); 
       } 
      });  
     } 
    }); 
    return p; 
} 
function reduceRemove_group2(p, v) { 
    if (v.items[0] === "") return p; // skip empty values 
    if (v.status[0] === "") return p; // skip empty values 
    v.items.forEach(function(val1, idx1){ 
     if (val1 === "apple"){ 
      v.status.forEach (function(val2, idx2) { 
       if (idx1 === idx2) { 
       p.A -= (val2 === 'A' ? 1 : 0); 
       p.O -= (val2 === 'O' ? 1 : 0); 
       p.C -= (val2 === 'C' ? 1 : 0); 
       p.R -= (val2 === 'R' ? 1 : 0); 
       } 
      });  
     } 
    }); 
    return p; 
} 
function reduceAdd_group3(p, v) { 
    if (v.items[0] === "") return p; // skip empty values 
    if (v.status[0] === "") return p; // skip empty values 
    v.items.forEach(function(val1, idx1){ 
     if (val1 === "orange"){ 
      v.status.forEach (function(val2, idx2) { 
       if (idx1 === idx2) { 
       p.A += (val2 === 'A' ? 1 : 0); 
       p.O += (val2 === 'O' ? 1 : 0); 
       p.C += (val2 === 'C' ? 1 : 0); 
       p.R += (val2 === 'R' ? 1 : 0); 
       } 
      });  
     } 
    }); 
    return p; 
} 
function reduceRemove_group3(p, v) { 
    if (v.items[0] === "") return p; // skip empty values 
    if (v.status[0] === "") return p; // skip empty values 
    v.items.forEach(function(val1, idx1){ 
     if (val1 === "orange"){ 
      v.status.forEach (function(val2, idx2) { 
       if (idx1 === idx2){ 
       p.A -= (val2 === 'A' ? 1 : 0); 
       p.O -= (val2 === 'O' ? 1 : 0); 
       p.C -= (val2 === 'C' ? 1 : 0); 
       p.R -= (val2 === 'R' ? 1 : 0); 
       } 
      });  
     } 
    }); 
    return p; 
} 
function reduceAdd_group4(p, v) { 
    if (v.items[0] === "") return p; // skip empty values 
    if (v.status[0] === "") return p; // skip empty values 
    v.items.forEach(function(val1, idx1){ 
     if (val1 === "meat"){ 
      v.status.forEach (function(val2, idx2) { 
       if (idx1 === idx2) { 
       p.A += (val2 === 'A' ? 1 : 0); 
       p.O += (val2 === 'O' ? 1 : 0); 
       p.C += (val2 === 'C' ? 1 : 0); 
       p.R += (val2 === 'R' ? 1 : 0); 
       } 
      });  
     } 
    }); 
    return p; 
} 
function reduceRemove_group4(p, v) { 
    if (v.items[0] === "") return p; // skip empty values 
    if (v.status[0] === "") return p; // skip empty values 
    v.items.forEach(function(val1, idx1){ 
     if (val1 === "meat"){ 
      v.status.forEach (function(val2, idx2) { 
       if (idx1 === idx2) { 
       p.A -= (val2 === 'A' ? 1 : 0); 
       p.O -= (val2 === 'O' ? 1 : 0); 
       p.C -= (val2 === 'C' ? 1 : 0); 
       p.R -= (val2 === 'R' ? 1 : 0); 
       } 
      });  
     } 
    }); 
    return p; 
} 
function reduceAdd_group(p, v) { 
    if (v.status[0] === "") return p; // skip empty values 
    v.status.forEach (function(val, idx) { 
     p[val] = (p[val] || 0) + 1; 
    }); 
    return p; 
} 
function reduceRemove_group(p, v) { 
    if (v.status[0] === "") return p; // skip empty values 
    v.status.forEach (function(val, idx) { 
     p[val] = (p[val] || 0) - 1; 
    }); 
    return p; 
} 
function reduceInitial_group() { 
    return { 
     A: 0, 
     O: 0, 
     C: 0, 
     R: 0 
    }; 
} 
function reduceInitial_items(){ 
    return { 
     count: 0, 
     state: '' 
    }; 
} 


//filter function: 
function myFilterFunction (dimension, filters) { 
    dimension.filter(null); 
    if (filters.length === 0) 
     dimension.filter(null); 
    else 
     dimension.filterFunction(function (d) { 
      for (var i=0; i < d.length; i++) { 
       if (filters.indexOf(d[i]) >= 0) return true; 
      } 
      return false; 
     }); 
    return filters; 
} 

//all function: 
function myAllFunction() { 
    var newObject = []; 
    for (var key in this) { 
     if (this.hasOwnProperty(key) && key != "all") { 
      newObject.push({ 
       key: key, 
       value: this[key] 
      }); 
     } 
    } 
    return newObject; 
}; 
+0

嗨凱西,實際上是問題的延續的答案是負責刪除SO。請使用此內容更新您的問題,以便將來有機會幫助他人。 – Gordon

+0

我忘了更新我的解決方案。謝謝! – Casey

相關問題