2016-04-27 12 views
1

私はDC.JS get last month value as filterに記載されているものと同様の問題があります。dc.jsの先月の値を追跡してフィルタリングします

つまり、私は棒グラフで、先月の株価を(企業および製品タイプごとに)表示したいと同時に、株価チャートを使って株価の進化を示しています。

そうするために、私は折れ線グラフをブラッシングして選択した最後の月を追跡する必要があります。 https://jsfiddle.net/BernG/wo60z64j/12/

var data = [{date:"201501",company:"A", product: "Prod1", stock:575} 
    , {date:"201502",company:"A", product: "Prod1", stock:325} 
    , {date:"201503",company:"A", product: "Prod1", stock:200} 
    , {date:"201504",company:"A", product: "Prod1", stock:450} 
    , {date:"201501",company:"A", product: "Prod2", stock:279} 
    , {date:"201502",company:"A", product: "Prod2", stock:93} 
    , {date:"201503",company:"A", product: "Prod2", stock:0} 
    , {date:"201504",company:"A", product: "Prod2", stock:372}  
    , {date:"201501",company:"A", product: "Prod3", stock:510} 
    , {date:"201502",company:"A", product: "Prod3", stock:340} 
    , {date:"201503",company:"A", product: "Prod3", stock:680} 
    , {date:"201504",company:"A", product: "Prod3", stock:170}  
    , {date:"201501",company:"B",product: "Prod1", stock:1000} 
    , {date:"201502",company:"B",product: "Prod1", stock:1100} 
    , {date:"201503",company:"B",product: "Prod1", stock:900} 
    , {date:"201504",company:"B",product: "Prod1", stock:1200} 
    , {date:"201501",company:"B",product: "Prod2", stock:1000} 
    , {date:"201502",company:"B",product: "Prod2", stock:1200} 
    , {date:"201503",company:"B",product: "Prod2", stock:900} 
    , {date:"201504",company:"B",product: "Prod2", stock:1200}   
    , {date:"201501",company:"B",product: "Prod3", stock:1000} 
    , {date:"201502",company:"B",product: "Prod3", stock:1100} 
    , {date:"201503",company:"B",product: "Prod3", stock:900} 
    , {date:"201504",company:"B",product: "Prod3", stock:600}]; 


// Reading and formatting values 
var dateFormat = d3.time.format('%Y%m'); 
data.forEach(function (d) { 
    d.dd = dateFormat.parse(d.date); 
    d.year = d3.time.year(d.dd); 
    d.month = d3.time.month(d.dd); 
}); 

// Definition of crossfilter and dimensions 
var  ndx = crossfilter(data) 
    , dimMonth = ndx.dimension(function(d){return d.month}) 
    , dimProduct = ndx.dimension(function(d){return d.product}) 
    , dimCompany = ndx.dimension(function(d){return d.company;}); 


var  lastStaticDate = dimMonth.top(1)[0].month;  // identify last date in full time domain 
var  firstStaticDate = dimMonth.bottom(1)[0].month; // identify first date in full time domain 


// Definition of a function to keep track of the last date value in the brush attached to the chartMonth. 
// If chartMonth object does not exist or its corresponding brush is empty (has not been brushed), then it returns the lastStaticDate 
// otherwise, it returns the last date in the brush selection 
var getLastDate = function(){ 
        if (typeof chartMonth === "undefined"){ // test if chartMonth is already in the DOM, if not return lastStaticDate 
         return lastStaticDate; 
         } 
        else { 
         if (chartMonth.brush().empty()) { // if chartMonth has been created but brush does not have have a selection 
          return lastStaticDate; 
          } 
         else { 
          return chartMonth.brush().extent()[1]; 
          }; 
         } 
        }; 

var lastDate = d3.time.month.ceil(getLastDate()); // lastDate is snapped to return a date where we have data in the x-domain 


dateBal.innerHTML = lastDate;  


var  grpMonth = dimMonth.group().reduceSum(function(d){return d.stock;}); // the line chart displays all values in the x-axis to show stock evolution 

// Definition of custom reduce functions      
function reduceAdd(p,v) { 
    if (p.month===lastDate){         
     p.stock += v.stock; 
     return p; 
     } 
    else {return p;} 
}; 

function reduceRemove(p,v) { 
    if (p.month!== lastDate){        
     p.stock -= v.stock; 
     return p;} 
    else {return p;} 
}; 

function reduceInitial() { 
    return {stock: 0} 
}; 

// Application of reduce functions 

var  grpCompany = dimCompany 
        .group() 
        .reduce(reduceAdd, reduceRemove, reduceInitial); 

var  grpProduct = dimProduct 
        .group() 
        .reduce(reduceAdd, reduceRemove, reduceInitial); 


var chartCompany = dc.barChart('#chartCompany'); 
var chartProduct = dc.barChart("#chartProduct"); 
var chartMonth = dc.lineChart('#chartMonth'); 

chartCompany 
    .width(400) 
    .height(400) 
    .margins({top: 50, right: 50, bottom: 50, left: 50}) 
    .dimension(dimCompany) 
    .group(grpCompany) 
    .x(d3.scale.ordinal()) 
    .xUnits(dc.units.ordinal) 
    .elasticY(true); 

chartProduct 
    .width(400) 
    .height(400) 
    .margins({top: 50, right: 50, bottom: 50, left: 50}) 
    .dimension(dimProduct) 
    .group(grpProduct) 
    .x(d3.scale.ordinal()) 
    .xUnits(dc.units.ordinal) 
    .elasticY(true); 


chartMonth 
    .width(400) 
    .height(400) 
    .margins({top: 50, right: 50, bottom: 50, left: 50}) 
    .renderlet(function (chart) { 
     // rotate x-axis labels 
     chart.selectAll('g.x text') 
     .attr('transform', 'translate(-10,10) rotate(315)'); 
     }) 
    .dimension(dimMonth) 
    .group(grpMonth) 
    .x(d3.time.scale().domain([firstStaticDate, lastStaticDate])) 
    .xUnits(d3.time.months) 
    .elasticX(true); 

dc.renderAll(); 

私は(ちなみに、受け入れとしてマークされていなかった、)上記の質問への回答のみに基づいていますしようとしたソリューションをし、このロジックは以下:ここに私のjsFiddleを参照してください

1 )まず、クロスフィルトデータセットの最後の日付を特定しようとします。初期化すると、ブラシが折れ線グラフ内で移動する前に、時間次元の最後の日付になります。それ以外の場合は、ブラシエクステント内の2番目の要素から日付を返します。この日までに、天井関数を適用して、返される日付が、時間次元の正確な日付として存在することを確認します。

2)現在の選択とは異なる月のデータを除いたカスタムリダクション関数を適用します。

私の具体的な質問は以下のとおりです。

  • にはどうすれば変数(lastDate)が反応することができますか?コンソールでうまくいきます:d3.time.month.ceil(getLastDate())。しかし、インタラクティブブラッシングイベントには反応しません。

  • 私のカスタムリダクション関数では、lastDateに対応する値だけを累積し、他の値はすべて除外する必要があります。何らかの理由で、顧客が現在定義されているように機能を削減すると、在庫値が正しく蓄積されません。

  • :私はgrpCompanyが存在する対象物を検査した場合たとえば、初期化時に、それはあなたが重複したとして、この質問をマークするために投票する前に次の点を考慮してください、最後に0 grpCompany.all() in console

    として株式の値を示して

  • 元の投稿には受け入れられた回答がないようです。
  • OPからjsFiddleが提供されていても提供されなかった場合は、オファーがありました。
  • 私は元の投稿で説明を明確にしたいと思っていましたが、これはできませんでした。なぜなら、コメントを投稿するために必要な評判はまだないからです。

答えて

0

これは本当に複雑です。そのため、私は前の質問に対して、Crossfilterがこれでうまくいかないと言ってコメントを始めました。私の答えは非常に複雑で、私が提案しようとしていたことはできませんでしたが、それはあなたのせいではありません。 Universeライブラリはあなたが示唆していることのいくつかをサポートしていますが、この複雑さを増しているならば、全体として私はあなたのアプローチを再考することをお勧めします。しかし、あなたのシナリオは前の質問と少し異なっており、簡単な答えがあります:

実際に行うべきことはカスタムdcを使うことです。JS filterFunctionの在庫残高チャートだけブラシで最後の日付にフィルタを作るために:

chartMonth 
    ... 
    .filterHandler(function(d,f) { 
    if(f.length > 0) { 
     d.filterExact(d3.time.month.ceil(f[0][1])); 
     dateBal.innerHTML = d3.time.month.ceil(f[0][1]); 
    } else { 
     d.filterAll(); 
     dateBal.innerHTML = "No month selected" 
    } 
    return f; 
    }) 

ここにあなたのJSFiddleに基づいて作業バージョンです:https://jsfiddle.net/esjewett/utohm7mq/2/

だから、それは単純な答えです。実際には、ブラシで選択された最後の月(または実際には次の月)まで、Crossfilter全体をフィルタリングするだけです。 ブラシによって選択された実際の日付に他のチャートをフィルタリングしたい場合は、複数のフィルタが矛盾していると言いますが、Crossfilterは現在これをうまくサポートしていません。私たちは、複数のフィルタグループをサポートする機能を追加することに関心がありますが、まだそれに取り組まずにいます。この場合、最良のアプローチはおそらく、2つの別々のCrossfiltersを維持し、異なるCrossfiltersから異なるチャートグループを駆動することです。

+1

迅速な回答ありがとうございます。提供されるソリューションは確かに非常に簡単で、完璧に機能します。私はf.length == 0の条件を含めるためにfilterHandlerをわずかに変更したので、lastStaticDateでフィルタを適用できます。これにより、棒グラフは、折れ線グラフの最後の日付に基づいてすでにフィルタリングされたページの読み込みに表示されます。 – BGutierrez

関連する問題