はじめに
前回は、データをグラフに表示する方法について説明しました。今回は、CSVファイルを読み込み、CSVファイルの内容をグラフに表示するアプリケーションを作成する方法を説明します。
これまでの記事
1.CSVファイルの読み込み
次のように、名前、身長、体重というカラムがあるCSVファイルがあったとします。
Allen,200,80 Smith,170,100 Scott,165,60 James,175,60
このCSVファイルをCurlで読み込むには、以下のようなコードを記述します。
{let records:CsvRecordSet =
{CsvRecordSet
{url "data.csv"}
, fields =
{RecordFields
{RecordField "name", caption = "Name", domain = String}
, {RecordField "height", caption = "height", domain = int}
, {RecordField "weight", caption = "weight", domain = int}
}
}
}
Curlの場合、このようにファイルのURLを指定するだけで、CSVファイルの読み込みとCsvRecordSetのインスタンス作成が可能です。
また、「{url "http://localhost:8080/sample/csvDownload.do"}」のように、httpのURLを指定するだけでネットワーク上のCSVファイルを読み込むこともできます。
次のファイルのようにヘッダ行を持ったCSVファイルの読み込みも可能です。ヘッダ行のあるファイルを読み込む場合は、header-line-countでヘッダの行数を指定するだけで対応できます。
name,height,weight Allen,200,80 Smith,170,100 Scott,165,60 James,175,60
{let records:CsvRecordSet =
{CsvRecordSet
{url "data.csv"}
|| ヘッダが存在する場合は、ヘッダの行数を指定する
, header-line-count = 1
, fields =
{RecordFields
{RecordField "name", caption = "Name", domain = String}
, {RecordField "height", caption = "height", domain = int}
, {RecordField "weight", caption = "weight", domain = int}
}
}
}
CurlではこのようにCSVファイルを読み込む機能があらかじめAPIとして提供されているため、コーディングは非常に簡単です。
2.読み込みんだデータをグラフにする
前回の記事では、データを作成しグラフを表示するには次のようなコードを記述しました。
{LayeredChart
width = 15cm
, height = 7.25cm
, left-axis = {new {NumericDataSeriesAxis-of float}
, {ChartDataSeries records, "height"}
, force-zero? = false
, force-range? = true
, forced-min = 130
, forced-max = 210
}
, {BubbleLayer
records
, "height"
, scatter-shape = "ellipse"
, x-axis-data = {ChartDataSeries records, "name"}
, primary-size-data = {ChartDataSeries records, "bmi"}
, secondary-size-data = {ChartDataSeries records, "bmi"}
}
}
上記コードのrecordsという変数は、RecordSetのインスタンスです。一方、CSVファイルデータを読み込んだデータを表すCsvRecordSetクラスはRecordSetを継承しているため、上記とまったく同じコードを記述するだけで対応できます。recordsという変数の位置にCsvRecordSetのインスタンスを渡せばグラフ化が可能です。
Javaなどでは、CSVファイルを扱うモジュールとグラフ化を行うモジュールが、異なるモジュールであるのが一般的なため、その間には型変換を行う処理が必要になってきます。しかし、Curlの場合、統一されたAPIとして提供されているので、スマートにデータの連携が行えます。
しかし、これだけのコードでは、CSVのデータにBMI値が含まれていないためエラーになってしまいますので、BMI値を計算し設定する必要があります。CsvRecordSetのインスタンスにBMI値を設定するコードは次のようになります。
{for record:Record in records do
set record["bmi"] = record["weight"]/((record["height"]/100)*(record["height"]/100))
}
これは、全レコードに対して、体重と身長からBMI値を計算し、設定するというコードです。RecordSetクラスは、JavaのMapのように、キーを指定してアクセスできます。
コード全体は次のようになります。
{curl 6.0 applet}
{curl-file-attributes character-encoding = "shift-jis"}
{import * from CURL.GUI.CHARTS}
{let records:CsvRecordSet =
{CsvRecordSet
{url "data.csv"}
|| ヘッダが存在する場合は、ヘッダの行数を指定する
, header-line-count = 1
, fields =
{RecordFields
{RecordField "name", caption = "Name", domain = String}
, {RecordField "height", caption = "height", domain = int}
, {RecordField "weight", caption = "weight", domain = int}
, {RecordField "bmi", caption = "bmi", domain = int}
}
}
}
|| BMIの計算と値の設定
{for record:Record in records do
set record["bmi"] = record["weight"]/((record["height"]/100)*(record["height"]/100))
}
{LayeredChart
width = 15cm
, height = 7.25cm
, left-axis = {new {NumericDataSeriesAxis-of float}
, {ChartDataSeries records, "height"}
, force-zero? = false
, force-range? = true
, forced-min = 130
, forced-max = 210
}
, {BubbleLayer
records
, "height"
, scatter-shape = "ellipse"
, x-axis-data = {ChartDataSeries records, "name"}
, primary-size-data = {ChartDataSeries records, "bmi"}
, secondary-size-data = {ChartDataSeries records, "bmi"}
}
}
3.サーバーサイドのデータをグラフ化する
RecordSetのインスタンスを作成出来てしまえば、グラフ化までの手数は少なくて済みます。
また、連載の第2回で紹介したJSONを利用したサーバーサイドとの連携でも、JSONデータからRecordSetへの変換処理は比較的簡単に行うことができました。
このように、Curlの中でデータを定義した場合だけではなく、サーバーサイドのデータをグラフ化することも比較的容易に行えるのが分かります。
|| サーバからのJsonデータの受信
{let empJsonValue: JsonValue =
{JsonValue-parse
{url "http://localhost:8080/curl_server/emp.json"}
}
}
|| Jsonデータを保管するレコード:customers
{let employees: RecordSet =
{RecordSet
{RecordFields
{RecordField "empno", caption = "empno", domain = int}
, {RecordField "ename", caption = "ename", domain = String}
, {RecordField "job", caption = "job", domain = String}
, {RecordField "mgr", caption = "mgr", domain = int}
, {RecordField "hiredate", caption = "hiredate", domain = double}
, {RecordField "sal", caption = "sal", domain = double}
, {RecordField "deptno", caption = "deptno", domain = int}
}
}
}
|| Jsonデータをcustomersに追加する
{define-proc public {add-rec
empno:int
, ename: String
, job: String
, mgr: int
, hiredate: double
, sal: double
, deptno: int
}: void
let new-rec: Record = {employees.new-record}
{new-rec.set "empno", empno}
{new-rec.set "ename", ename}
{new-rec.set "job", job}
{new-rec.set "mgr", mgr}
{new-rec.set "hiredate", hiredate}
{new-rec.set "sal", sal}
{new-rec.set "deptno", deptno}
{employees.append new-rec}
}
{for emp: JsonObject in empJsonValue do
let empno: int = 0
let ename: String = {String}
let job: String = {String}
let mgr: int = 0
let hiredate: double = 0
let sal: double = 0
let deptno: int = 0
set empno = {emp.get "empno"}
set ename = {emp.get "ename"}
set job = {emp.get "job"}
set mgr = {emp.get "mgr"}
set hiredate = {emp.get "hiredate"}
set sal = {emp.get "sal"}
set deptno = {emp.get "deptno"}
{add-rec empno, ename, job, mgr, hiredate, sal, deptno}
}
4.まとめ
Curlでは、CSVファイルにアクセスするためのURLが分かっていれば、容易にグラフ化を行うことができます。Strutsでできたアプリケーションであっても、CSVファイルをダウンロードするURLが分かっていれば同様に可能です。また、サーバーサイドのデータをグラフ化することも容易に行えます。既存アプリのビューとしてCurlを利用するのも面白いのではないでしょうか。
次回は、JavaとCurlの文法などの比較を行います。



