web-dev-qa-db-ja.com

D3v5でd3.csvを使用してデータを動的にロードする

バックエンドから部分的にデータをロードするd3.jsで動的にロードする棒グラフを作成しようとしています。 d3.csv()関数を使用して、最初の描画のためにデータから最初のn行数だけを読み取り、その後JSロジックに従って後続のデータをロードする方法はありますか?

tl; drd3.csv()関数内のデータに選択的にアクセスしたい。

私はこれのために以下のコードを実行しようとしています:

var margin = {
            top: 20,
            bottom: 30,
            left: 40,
            right: 30
        },
        width = 600 - margin.left - margin.right,
        height = 500 - margin.top - margin.bottom;

    var loadData = function() {
        d3.csv("test_data.csv", function(data) {
            console.log(data.filter(function(d, i) {
                return i < 2;
            }));

            console.log(data.filter(function(d, i) {
                return i < 3;
            }))
        })
    }

    loadData();

ただし、コンソールでエラーが発生します。

Uncaught(in promise)TypeError:data.filter is not a function(…)

これは、このデータが配列ではないと私に信じさせます。これは事実ですか、それとも私はここで他の問題に直面していますか?

また、このd3.csv関数内の列(csvファイル内)にアクセスするにはどうすればよいですか? (たとえば、私のcsvデータファイルにaとbという名前の2つの列が含まれている場合)。

5
V_S_X

まず、CSVの最初のn行だけをd3.csvでロード/解析する方法はありません。それは不可能だと思います。残念ながら、すべてのファイルをロード/解析する必要があります。これは、ファイルが巨大な場合に不便になる可能性があります。つまり、ユーザーは、チャートが描画される前に、ファイル全体がロード/解析されるのを待つ必要があります。また、d3.csvはすべてのファイルをロードするため、後続のフィルターは関係ありません。必要なデータの行を使用し、ブラウザーに不要なタスクを追加せずに、必要な行を使用してください。チャートのペイント。

主な質問に戻ります。

データは配列です。ここでの問題は、d3.csvをXHRであるかのように使用していることです。これは、D3 v4の場合です...ただし、D3 v5では、d3.csvは約束です。

したがって、次のようにする必要があります。

d3.csv(url).then(callback);

以下のデモをご覧ください。

var csv = URL.createObjectURL(new Blob([
  `foo,bar,baz
12,43,21
45,54,21
87,13,17
98,69,17`
]));

d3.csv(csv).then(function(data) {
  console.log(data.filter(function(d, i) {
    return i < 2;
  }));
})
<script src="https://d3js.org/d3.v5.min.js"></script>

2番目の質問に関して、d3.csvcolumnsという名前の配列プロパティの列を公開します。

var csv = URL.createObjectURL(new Blob([
  `foo,bar,baz
12,43,21
45,54,21
87,13,17
98,69,17`
]));

d3.csv(csv).then(function(data) {
  console.log("columns are: " + data.columns)
})
<script src="https://d3js.org/d3.v5.min.js"></script>
6
Gerardo Furtado

Gerardo Furtadoの答えに追加する1つのこと:あなたの例は次のように構成されています:

_d3.csv('some_file.csv', someFunction)
_

_d3.csv_ V5では、関数がこのように引数として渡されると、ごとに1回呼び出されますrow object は、その行、そのインデックス、および列キーの配列を表し、行を変更できるようにします。したがって、特定のエラーは、このコールバックの最初の引数が、データセットを表す配列ではなく、行を表すオブジェクトであるためです。

次に、それらがすべて完了すると、promiseが完了し、.then(someFunction)で提供されるコールバックが発生します。

_d3.csv('some_file.csv', transformRow).then(processData)
_

transformRow関数はオプションです。提供されている場合、各行に対して返されるものはすべて、データ内のその行を置き換えます。

次に、processDataコールバックは、 original 列名の配列であるプロパティcolumnsを持つ行の配列を取得します(したがって、transformRowは、異なるプロパティキーを持つオブジェクトを返します。_data.columns_は各行のプロパティと一致しません)。

したがって、たとえば:

_    var csv = URL.createObjectURL(new Blob([
     `name,start,end
      SOMETHING,123,321
      INVALID,321,123
      ANOTHER,111,333`
    ]));

    d3.csv(csv, processRow).then(processData)
    
    function processRow (row, index, columnKeys) {
      row[columnKeys[0]] = row[columnKeys[0]].trim().toLowerCase()
      row.duration = row.end - row.start // this new property doesn't change data.columns
      if (row.end > row.start) return row
    }
    
    function processData (data) {
      console.log(data, data.columns)
    }_
_<script src="https://d3js.org/d3.v5.min.js"></script>_