コンテンツへスキップ

d3-dsv

このモジュールは、区切り文字で区切られた値(通常はカンマ区切り値 (CSV)またはタブ区切り値 (TSV))のパースとフォーマットを提供します。これらの表形式は、Microsoft Excelなどの表計算ソフトでよく使用され、JSONよりも多くの場合、スペース効率が高いです。この実装はRFC 4180に基づいています。

例:パース

js
d3.csvParse("foo,bar\n1,2") // [{foo: "1", bar: "2"}, columns: ["foo", "bar"]]
js
d3.tsvParse("foo\tbar\n1\t2") // [{foo: "1", bar: "2"}, columns: ["foo", "bar"]]

フォーマット

js
d3.csvFormat([{foo: "1", bar: "2"}]) // "foo,bar\n1,2"
js
d3.tsvFormat([{foo: "1", bar: "2"}]) // "foo\tbar\n1\t2"

パイプ区切り値(「|」)など、別の区切り文字を使用するには、d3.dsvFormatを使用します。

js
d3.dsvFormat("|").parse("foo|bar\n1|2")) // [{foo: "1", bar: "2"}, columns: ["foo", "bar"]]

ブラウザでのDSVファイルの簡単な読み込みについては、d3-fetchd3.csvd3.tsvd3.dsvメソッドを参照してください。

dsvFormat(delimiter)

js
const csv = d3.dsvFormat(",");

ソースコード · 指定されたdelimiter(区切り文字)に対して新しいDSVパーサーとフォーマッターを作成します。delimiterは1文字(つまり、16ビットコードユニット1つ)でなければなりません。そのため、ASCII区切り文字は問題ありませんが、絵文字区切り文字は使用できません。

dsv.parse(string, row)

注意

このメソッドには、unsafe-eval コンテンツセキュリティポリシーが必要です。

js
d3.csvParse("foo,bar\n1,2") // [{foo: "1", bar: "2"}, columns: ["foo", "bar"]]

ソースコード · 指定されたstring(文字列)をパースします。この文字列は、適切な区切り文字を使用した区切り文字で区切られた値の形式でなければなりません。パースされた行を表すオブジェクトの配列を返します。

dsv.parseRowsとは異なり、このメソッドでは、DSVコンテンツの最初の行に、区切り文字で区切られた列名のリストが含まれている必要があります。これらの列名は、返されるオブジェクトのプロパティになります。たとえば、次のCSVファイルについて考えてみます。

Year,Make,Model,Length
1997,Ford,E350,2.34
2000,Mercury,Cougar,2.38

結果として得られるJavaScript配列は次のとおりです。

js
[
  {"Year": "1997", "Make": "Ford", "Model": "E350", "Length": "2.34"},
  {"Year": "2000", "Make": "Mercury", "Model": "Cougar", "Length": "2.38"}
]

返された配列は、入力順序で列名を含むcolumnsプロパティも公開します(Object.keysとは対照的に、その反復順序は任意です)。例:

js
data.columns // ["Year", "Make", "Model", "Length"]

列名が重複している場合、各名前に対して最後の値のみが返されます。すべての値にアクセスするには、代わりにdsv.parseRowsを使用してください(を参照)。

row変換関数が指定されていない場合、フィールド値は文字列になります。安全のため、数値、日付、その他の型への自動変換はありません。場合によっては、JavaScriptが文字列を数値に自動的に強制変換することがあります(たとえば、+演算子を使用する場合)。しかし、row変換関数を指定する方が良いです。d3.autoTypeは、数値や文字列などの一般的な型を推論して強制変換する便利なrow変換関数です。

row変換関数が指定されている場合、指定された関数は各行に対して呼び出され、現在の行を表すオブジェクト(d)、0から始まるインデックス(i)(最初のヘッダー行以外)、列名の配列が渡されます。返された値がnullまたはundefinedの場合、その行はスキップされ、dsv.parseによって返される配列から省略されます。それ以外の場合は、返された値によって対応する行オブジェクトが定義されます。例:

js
const data = d3.csvParse(string, (d) => {
  return {
    year: new Date(+d.Year, 0, 1), // lowercase and convert "Year" to Date
    make: d.Make, // lowercase
    model: d.Model, // lowercase
    length: +d.Length // lowercase and convert "Length" to number
  };
});

注:parseIntまたはparseFloatではなく、+またはNumberを使用する方が、一般的に高速ですが、より制限的です。たとえば、"30px"+を使用して強制変換するとNaNが返されますが、parseIntとparseFloatは30を返します。

dsv.parseRows(string, row)

js
d3.csvParseRows("foo,bar\n1,2") // [["foo", "bar"], ["1", "2"]]

ソースコード · 指定されたstring(文字列)をパースします。この文字列は、適切な区切り文字を使用した区切り文字で区切られた値の形式でなければなりません。パースされた行を表す配列の配列を返します。

dsv.parseとは異なり、このメソッドはヘッダー行を標準行として扱い、DSVコンテンツにヘッダーが含まれていない場合に使用されるべきです。各行はオブジェクトではなく配列として表されます。行の長さは可変です。たとえば、ヘッダー行がない次のCSVファイルについて考えてみます。

1997,Ford,E350,2.34
2000,Mercury,Cougar,2.38

結果として得られるJavaScript配列は次のとおりです。

js
[
  ["1997", "Ford", "E350", "2.34"],
  ["2000", "Mercury", "Cougar", "2.38"]
]

row変換関数が指定されていない場合、フィールド値は文字列になります。安全のため、数値、日付、その他の型への自動変換はありません。場合によっては、JavaScriptが文字列を数値に自動的に強制変換することがあります(たとえば、+演算子を使用する場合)。しかし、row変換関数を指定する方が良いです。d3.autoTypeは、数値や文字列などの一般的な型を推論して強制変換する便利なrow変換関数です。

row変換関数が指定されている場合、指定された関数は各行に対して呼び出され、現在の行を表す配列(d)、0から始まるインデックス(i)(最初の行)、列名の配列が渡されます。返された値がnullまたはundefinedの場合、その行はスキップされ、dsv.parseによって返される配列から省略されます。それ以外の場合は、返された値によって対応する行オブジェクトが定義されます。例:

js
const data = d3.csvParseRows(string, (d, i) => {
  return {
    year: new Date(+d[0], 0, 1), // convert first column to Date
    make: d[1],
    model: d[2],
    length: +d[3] // convert fourth column to number
  };
});

事実上、rowは、返された行にmapfilter演算子を適用することと似ています。

dsv.format(rows, columns)

js
d3.csvFormat([{foo: "1", bar: "2"}]) // "foo,bar\n1,2"
js
d3.csvFormat([{foo: "1", bar: "2"}], ["foo"]) // "foo\n1"

ソースコード · オブジェクトrows(行)の配列を区切り文字で区切られた値としてフォーマットし、文字列を返します。この操作はdsv.parseの逆です。各行は改行文字(\n)で区切られ、各行内の各列は区切り文字(カンマ(,)など)で区切られます。区切り文字、二重引用符(")、または改行文字を含む値は、二重引用符を使用してエスケープされます。

columnsが指定されていない場合、ヘッダー行を形成する列名のリストは、rows内のすべてのオブジェクトのすべてプロパティの和集合によって決定されます。列の順序は非決定論的です。columnsが指定されている場合、それは列名を表す文字列の配列です。例:

js
const string = d3.csvFormat(data, ["year", "make", "model", "length"]);

各行オブジェクトのすべてのフィールドは文字列に変換されます。フィールド値がnullまたはundefinedの場合、空文字列が使用されます。フィールド値がDateの場合、ECMAScript日付時刻文字列形式(ISO 8601のサブセット)が使用されます。たとえば、UTC深夜の日付はYYYY-MM-DDとしてフォーマットされます。どのフィールドをどのようにフォーマットするかをより細かく制御するには、まずrowsを文字列の配列の配列にマップし、次にdsv.formatRowsを使用します。

dsv.formatBody(rows, columns)

js
d3.csvFormatBody([{foo: "1", bar: "2"}]) // "1,2"
js
d3.csvFormatBody([{foo: "1", bar: "2"}], ["foo"]) // "1"

ソースコード · dsv.formatと同等ですが、ヘッダー行は省略されます。これは、たとえば、既存のファイルに行を追加する場合に便利です。

dsv.formatRows(rows)

js
d3.csvFormatRows([["foo", "bar"], ["1", "2"]]) // "foo,bar\n1,2"

ソースコード · 文字列の配列の配列であるrowsを区切り文字で区切られた値としてフォーマットし、文字列を返します。この操作はdsv.parseRowsの逆です。各行は改行文字(\n)で区切られ、各行内の各列は区切り文字(カンマ(,)など)で区切られます。区切り文字、二重引用符(")、または改行文字を含む値は、二重引用符を使用してエスケープされます。

列を明示的に指定しながら、オブジェクトの配列を配列の配列に変換するには、array.mapを使用します。例:

js
const string = d3.csvFormatRows(data.map((d, i) => {
  return [
    d.year.getUTCFullYear(), // Assuming d.year is a Date object.
    d.make,
    d.model,
    d.length
  ];
}));

必要であれば、この結果に列名の配列をarray.concatして、最初の行を生成することもできます。

js
const string = d3.csvFormatRows([[
    "year",
    "make",
    "model",
    "length"
  ]].concat(data.map((d, i) => {
  return [
    d.year.getUTCFullYear(), // Assuming d.year is a Date object.
    d.make,
    d.model,
    d.length
  ];
})));

dsv.formatRow(row)

js
d3.csvFormatRow(["foo", "bar"]) // "foo,bar"

ソースコード · 文字列の単一配列 *行* を区切り文字で区切られた値としてフォーマットし、文字列を返します。行内の各列は、区切り文字(カンマ,など)で区切られます。区切り文字、二重引用符(")、または改行を含む値は、二重引用符を使用してエスケープされます。

dsv.formatValue(value)

js
d3.csvFormatValue("foo") // "foo"

ソースコード · 単一の *value* または文字列を区切り文字で区切られた値としてフォーマットし、文字列を返します。区切り文字、二重引用符(")、または改行を含む値は、二重引用符を使用してエスケープされます。

csvParse(string, row)

d3.dsvFormat(",")parse と同等です。

csvParseRows(string, row)

d3.dsvFormat(",").parseRows と同等です。

csvFormat(rows, columns)

d3.dsvFormat(",").format と同等です。

csvFormatBody(rows, columns)

d3.dsvFormat(",").formatBody と同等です。

csvFormatRows(rows)

d3.dsvFormat(",").formatRows と同等です。

csvFormatRow(row)

d3.dsvFormat(",").formatRow と同等です。

csvFormatValue(value)

d3.dsvFormat(",").formatValue と同等です。

tsvParse(string, row)

d3.dsvFormat("\t").parse と同等です。

tsvParseRows(string, row)

d3.dsvFormat("\t").parseRows と同等です。

tsvFormat(rows, columns)

d3.dsvFormat("\t").format と同等です。

tsvFormatBody(rows, columns)

d3.dsvFormat("\t").formatBody と同等です。

tsvFormatRows(rows)

d3.dsvFormat("\t").formatRows と同等です。

tsvFormatRow(row)

d3.dsvFormat("\t").formatRow と同等です。

tsvFormatValue(value)

d3.dsvFormat("\t").formatValue と同等です。

autoType(object)

ソースコード · パースされた行を表す *object*(または配列)を元に、*object*内の値の型を推測し、それに応じて強制変換を行い、変更された*object*を返します。この関数は、dsv.parseおよびdsv.parseRowsと連携して*row*アクセサ関数として使用することを目的としています。例えば、以下のCSVファイルを考えてみましょう。

Year,Make,Model,Length
1997,Ford,E350,2.34
2000,Mercury,Cougar,2.38

d3.csvParseで使用した場合、

js
d3.csvParse(string, d3.autoType)

結果として得られるJavaScript配列は次のようになります。

js
[
  {"Year": 1997, "Make": "Ford", "Model": "E350", "Length": 2.34},
  {"Year": 2000, "Make": "Mercury", "Model": "Cougar", "Length": 2.38}
]

型推論は次のように機能します。指定された *object* 内の各 *value* に対して、トリムされた値が計算されます。その後、値は次のように再割り当てされます。

  1. 空の場合、null
  2. 正確に"true"の場合、true
  3. 正確に"false"の場合、false
  4. 正確に"NaN"の場合、NaN
  5. それ以外で、数値に変換可能な場合、数値。
  6. それ以外で、日付のみまたは日時文字列の場合、Dateオブジェクト。
  7. それ以外の場合、文字列(元のトリムされていない値)。

先頭にゼロが付いた値は数値に変換される場合があります。たとえば、"08904"8904に変換されます。ただし、カンマや単位などの余分な文字(例:"$1.00""(123)""1,234""32px")があると数値への変換が行われず、文字列になります。

日付文字列は、ECMAScriptのISO 8601形式のサブセットである必要があります。YYYY-MM-DDなどの日付のみの文字列を指定した場合、推測される時刻はUTCの午前0時です。ただし、タイムゾーンなしでYYYY-MM-DDTHH:MMなどの日時文字列を指定した場合は、ローカル時間とみなされます。

自動型推論は、主に一般的なJavaScript型に対してdsv.formatおよびdsv.formatRowsと連携して安全で予測可能な動作を提供することを目的としています。異なる動作が必要な場合は、独自の行アクセサ関数を実装する必要があります。

詳細については、d3.autoTypeノートブックを参照してください。

コンテンツセキュリティポリシー

コンテンツセキュリティポリシーが有効になっている場合、高速なパースのために動的なコード生成(安全な方法)を使用しているため、dsv.parseにはscript-srcディレクティブにunsafe-evalが必要です。(ソースコードを参照)。または、dsv.parseRowsを使用してください。

バイトオーダーマーク

DSVファイルは、バイトオーダーマーク(BOM)で始まる場合があります。たとえば、Microsoft ExcelからCSV UTF-8形式でスプレッドシートを保存すると、BOMが含まれます。ウェブ上では、Encoding標準で指定されているUTF-8デコードアルゴリズムがBOMを削除するため、通常は問題になりません。一方、Node.jsはUTF-8のデコード時にBOMを削除しません

BOMが削除されない場合、テキストの最初の文字はゼロ幅非改行スペースになります。そのため、BOM付きのCSVファイルがd3.csvParseによってパースされると、最初の列の名前はゼロ幅非改行スペースで始まります。この文字は印刷時に通常は表示されないため、見つけるのが困難です。

パース前にBOMを削除するには、strip-bomの使用を検討してください。