web-dev-qa-db-ja.com

D3.jsを使用して視覚化するためのローカルデータの読み込み

私は、かなり複雑なタイプのデータを視覚化する必要があるプロジェクトに取り組んでいます( この古い質問 を参照)。要するに、JSON、CSV、またはその他の任意のフラット形式にエクスポートできるデータの大きなチャンクがありますが、可能であればXMLは避けたいと思います(基になるデータの詳細な説明については、上記のリンクされた質問を参照してください)。

D3を使用して視覚化の作業を開始しました。これまでに作成したレイアウトは、Javascriptに配列としてハードコーディングした非常に単純なデータでテストすると問題なく機能するようです。 D3でのデータバインディングについて読んだチュートリアルは、JSONを使用するもの、TXT/CSV形式を使用するもの、ハードコードされた配列/行列を使用するものがあるという意味で少し混乱しています。

JSONの場合、ナレーターがWebサーバーでJSONファイルをホストし、ローカルファイルの読み取りではなくHTTPリクエストを使用して取得するようにしっかりとアドバイスするチュートリアルを見ました。これはクロスドメインリクエストの制限によるものであり、何らかの方法で回避する必要があると思います。現時点では、次の理由からどのように進めるかわかりません。

  1. D3を利用した視覚化は、私が作成した分析ツールの結果として作成された一連のHTMLレポートで行われます。分析はユーザーのコンピューターで実行され、HTMLレポートもクライアント側でローカルに作成されます。

  2. 対象となるユーザーは間違いなく技術に精通していないため、ローカルホストを介してJSONまたはその他のタイプやリソースを提供できるようにコンピューターでWebサーバーを実行するように指示するオプションはありません。

記録のために、python SimpleHTTPServerモジュールを実行して試してみましたが、すべて正常に動作します。次に、生成されたHTMLレポートにデータをハードコーディングしてから、を呼び出します。 D3を使用するスクリプトのJSONオブジェクト、

//d3.json("mydata.json", function(json){
d3.json(myjson, function(json){
    nodeData = json.elements;
....
}

その場合、D3.jsがURLを期待している間にJSONオブジェクトを送信することになり、失敗します。

この問題を回避/解決するにはどうすればよいですか?

13
posdef

サーバーを使用せずにデータローカルファイルをロードするには、予期している変数またはオブジェクト要素にソースデータが割り当てられたスクリプトタグを本文に追加します。以下の例では、[COUNTRY_ISO3CODE] .jsファイルから特定の国のデータを読み込みます。具体的には、アフガニスタンのデータファイルの内容は次の形式である可能性があります。

data[AFG] = {"name": "Afghanistan", "estimate": 9.003, ... }

呼び出しファイルは次のようになります。

if (!data[iso3]) { //only load the needed data-script as needed

    // if using jQuery
    $('body').append("<script type='text/javascript' src='jdb/"+ iso3 +".js'></script>")

    //If not using jQuery
    /*var script   = document.createElement("script");
    script.type  = "text/javascript";
    script.src   = "jdb/"+iso3+".js"; //?_="+ (new Date()); URL might have to be randomized to avoid cached data
    document.body.appendChild(script);
    */

    // call the data-handling function only after 
    // the desired data has fully loaded
    // in this case, I check every 100 milliseconds
    var intervalId = setInterval( function () {
        if (data[iso3]) {    //once data is detected, process data
            clearInterval(intervalId); //stop checking for data
            prepData(mainWrapper, iso3)
            drawCharts(mainWrapper, iso3)
        }
    }, 100)
}
else drawCharts(mainWrapper, iso3)
2
Edgar

したがって、FileReader呼び出しを介してローカルデータをロードする場合、以下のものは JavaScriptでローカルファイルを読み取る から取得されます。ただし、上記の例に基づいて、このコードはファイルをリンクせずに画像ファイルをsvgにロードしますが、実際にはラスターデータをsvgに挿入します。そして、ラスターデータをanyの他のデータに自由に置き換えて、正しい処理を追加するだけです...

まず、<body>セクションでサポートされているhtml要素をオフにします。

<input type="file" id="files" name="files[]" multiple />

次に、<input ... />要素を<script>セクションのコードにリンクします。

document.getElementById('files').addEventListener('change', handleFileSelect, false);

これで、ファイルの背後にあるコードがイベント処理コードで読み取られました(この場合、ローカルイメージをD3JS svgにロードします):

function handleFileSelect(evt) {
    reader = new FileReader();
    reader.onabort = function(e) {alert('File read cancelled');};
    var imageObj = new Image();  //image object to hold the local file contents.

    //and given the asynchronous nature, set up the event so that when the image is loaded, do something with it:
    imageObj.onload = function() {image.datum(imageObj.src).attr("xlink:href", function(d) {return d})};

    //similarly for the file reading:
    reader.onload = function(e) {imageObj.src = reader.result};

    //With all the events set up, lets start reading the file in.
    //the secret sauce is the DataURL
    reader.readAsDataURL(evt.target.files[0]);
}

そして完全を期すために、画像の背後にあるD3JSソース:

var svg = d3.select("body").append("svg");

var image = svg.append("defs")
    .append("pattern")
    .attr("id", "venus")
    .attr('patternUnits', 'userSpaceOnUse')
    .attr("width", 200)
    .attr("height", 200)
    .append("image")
    .attr("width", 200)
    .attr("height", 200);

var image2 = svg.append("rect")
    .attr("x", "0")
    .attr("y", "0")
    .attr("width", 200)
    .attr("height", 200)
    .attr("fill", "url(#venus)");
2
Mike

JSONの場合:

var data = JSON.parse(JavascriptStringVariableThatContainsJSON);

CSVの場合:

 var data = d3.csv.parseRows(JavascriptStringVariableThatContainsMyCSVdata);

//次に、グラフにデータを追加し、次のようにEnterを呼び出します。

 var dataEnter = svg.selectAll("rect").data(data).enter();
2
pilavdzice

毎回HTMLを生成する場合は、データをJSONとして、HTML内、またはHTMLから参照できる.jsファイル(おそらく生成された一意のURLを介して)に配置できます。

1
Joseph Boyle

d3.jsonはajax呼び出しを介して外部jsonファイルをロードします-例のmyjson変数はすでにjavascriptオブジェクトであるため、ロードする必要はなく、nodeData割り当てで直接使用するだけです。

nodeData = myjson.elements;
0
David Burrows

D3には、データをインポートして操作するための優れたツールがいくつかあります。過去に常にjsonを提供してきましたが(作成するのが面倒な場合もあります)、csvを提供し、javascript/d3で操作することに取り組んでいますが、他の人があなたの質問にどのように応答するかを確認したいと思います。

これは、ネストされたjsonにcsvを表示する簡単な例です: https://Gist.github.com/3053667

また、データを操作するための多くのツール: https://github.com/mbostock/d3/wiki/Arrays

そして、スライスしてさいの目に切る場合は、クロスフィルターがあります。理解する価値があるように見えますが、ダミーガイドが出てくるのを待っています! http://square.github.com/crossfilter/

0
PhoebeB