28

値として配列を持つクロスフィルター データセットをフィルター処理することは可能ですか?

たとえば、次のデータセットがあるとします。

var data = [
  {
    bookname: "the joy of clojure",
    authors: ["Michael Fogus", "Chris Houser"],
    tags: ["clojure", "lisp"]
  },
  {
    bookname: "Eloquent Ruby",
    authors: ["Russ Olsen"],
    tags: ["ruby"]
  },
  {
    bookname: "Design Patterns in Ruby",
    authors: ["Russ Olsen"],
    tags: ["design patterns", "ruby"]
  }
];

特定のタグでタグ付けされた本に簡単にアクセスする方法はありますか? また、特定の著者がいる本は?これまでのクロスフィルターの使用方法を理解する方法は、次のようなことです。

var filtered_data = crossfilter(data);
var tags = filtered_data.dimension(function(d) {return d.tags});
var tag = tags.group();

そして、グループ化にアクセスすると(そのように):

tag.all()

私はこれを得る:

[{key: ["clojure", "lisp"], value: 1}, 
 {key: ["design patterns", "ruby"], value: 1}, 
 {key: ["ruby"], value: 1}]

私がむしろこれを持っているとき:

[{key: "ruby", value: 2}, 
 {key: "clojure", value: 1}, 
 {key: "lisp", value: 1},
 {key: "design patterns", value: 1}]
4

2 に答える 2

31

以下のコードにコメントを追加しました。全体像: reduce 関数を使用します。

var data = ...
var filtered_data = crossfilter(data);
var tags = filtered_data.dimension(function(d) {return d.tags});

tags.groupAll().reduce(reduceAdd, reduceRemove, reduceInitial).value()

group() b/cの代わりにgroupAll()を使用した方法に注意してください。reduce関数 (以下で定義) を 3 つのグループではなく 1 つのグループで操作する必要があります。

reduce 関数は次のようになります。

/*
 v is the row in the dataset

 p is {} for the first execution (passed from reduceInitial). 
 For every subsequent execution it is the value returned from reduceAdd of the prev row
*/
function reduceAdd(p, v) {
  v.tags.forEach (function(val, idx) {
     p[val] = (p[val] || 0) + 1; //increment counts
  });
  return p;
}

function reduceRemove(p, v) {
   //omitted. not useful for demonstration
}

function reduceInitial() {
  /* this is how our reduce function is seeded. similar to how inject or fold 
   works in functional languages. this map will contain the final counts 
   by the time we are done reducing our entire data set.*/
  return {};  
}
于 2012-08-30T07:15:14.767 に答える
2

私は「クロスフィルター」を使ったことがありません(これはJSライブラリだと思います)。ただし、ここにいくつかの純粋なJSメソッドがあります。

これ...

data.filter(function(d) {
  return d.authors.indexOf("Michael Fogus") !== -1;
})

これを返します:

[{bookname:"the joy of clojure", authors:["Michael Fogus", "Chris Houser"], tags:["clojure", "lisp"]}]

これ...

var res = {};
data.forEach(function(d) {
  d.tags.forEach(function(tag) {
    res.hasOwnProperty(tag) ? res[tag]++ : res[tag] = 1
  });
})

これを返します:

({clojure:1, lisp:1, ruby:2, 'design patterns':1})

これらのいずれかに、あなたはあなたのフォーマットd3.entriesを得るために申し込むことができます。{key:"ruby", value: 2}

于 2012-08-20T22:06:55.657 に答える