スクリプトによるデータ解析とグラフ描画

CSVで記録されたNXT走行体の走行ログには、各種センサーからの入力値やモーターの動きが数値として連続的に記録されている。
走行体の動きを把握するためにはこのデータの分析が必須だが、市販の表計算ソフトを使って処理しようとするとデータ量が多いので、 1つ1つのファイルを読み込んで描画すると、操作に多大な時間がかかり効率が悪い。
ここでは、スクリプト言語(groovy)とグラフ化ツール(gnuplot)を用いて、効率的にデータを処理する簡単な方法を紹介する。

なお、ここで紹介するスクリプトやデータは、以下のzipファイルにまとめてあるので、必要に応じて参照すること。

DataAnalysisAndDrawGraph20130617.zip

実行環境構築

今回は、Cygwin環境下で、javaのjvm上で動作するスクリプト言語groovyを使用するので、その環境を用意する。

Java 実行環境のインストール

以下のURLより、最新版のJDKを入手して、インストールする。

http://www.oracle.com/technetwork/java/javase/downloads/index.html

Cygwin環境へのパッケージ追加

Cygwinのパッケージ管理ツールを使って以下のパッケージを追加する。

 |— Net
 | |— curl
 |
 |— Graphics
 | |— gnuplot

GVMのインストール

GVM: Groovy enVironment Managerは、cygwin上で、groovyに必要な環境を自動でインストールしてくれるパッケージマネージャーである。 cygwinから、以下のコマンドを実行してインストールする。

$ curl -s get.gvmtool.net | bash

groovyのインストール

先ほどインストールしたGVMを初期化するために、以下のコマンドを実行する。

$ .gvm/bin/gvm-init.sh

次に、以下のコマンドを実行してgroovyをインストールする。

$ gvm install groovy

以下は、必要に応じて実行すること。

$ gvm list groovy   # 利用可能なバージョンのチェック
$ gvm selfupdate    # gvmのバージョンアップ

また、以下のツールは便利なので、必要に応じてインストールするとよい。

$ gvm install grails    # Ruby on Railsライクな開発を行えるWebアプリケーションフレームワーク
$ gvm install griffon   # Grailsと同様の使い勝手でデスクトップアプリケーションを構築することができるフレームワーク
$ gvm install gradle    # Groovyで書かれたビルドシステム

データ処理と加工

Step 1

ログデータの読み出し

まず、ログデータを読み出してみる。
使用するログデータは、以下のファイルを使用する。そのサイズは、34375行のデータである。

$ wc 20130613_183553.csv
  34375   34385 1841244 20130613_183553.csv

ソースリスト

class readLine {
    static void main(args){
        def f = new File(args[0]) // ファイルを開く。
        f.eachLine { line ->      // 1行づつ読み込む。
            println(line)         // それを1行づつ表示する。
        }
    }
}

実行

$ groovy readLine.groovy 20130613_183553.csv

これは、catコマンドと同じである。

$ cat 20130613_183553.csv

Step 2

ログデータを行単位で読み出し、要素に分解した後にタブ区切りで表示する。

ソースリスト

class readLineSplit {
    static void main(args){
        def f = new File(args[0]) // ファイルを開く。
        // ファイルから1行づつ読み込む。
        f.eachLine { line ->             
             // カンマを区切りの単位として分割。
            def column = line.split(",")
            column.each {  // Tab区切りで表示
            print(it + '¥t')         
        }
        print('¥n') 
    }
}

実行

$ groovy readLineSplit.groovy 20130613_183553.csv

Step 3

1カラム目の時間データと、10カラム目の光センサのデータを情報を取り出し、タブ区切りで出力する。

ソースリスト

class readLineSplitSelect {
    static void main(args){
        print("# ")
        def f = new File(args[0]) // ファイルを開く。
        // ファイルから1行づつ読み込む。
        f.eachLine { line ->
            // カンマを区切りとして分割。
            def column = line.split(",")
            // カラム0,9をTab区切りで表示
            println(column[0] + "¥t" + column[9])
        }
    }
}

実行

最初は、タブ区切りの出力をそのまま表示する。

$ groovy readLineSplitSelect.groovy 20130613_183553.csv

次に、タブ区切りの出力をリダイレクトで、photo.datに保存する。

$ groovy readLineSplitSelect.groovy 20130613_183553.csv > photo.dat

グラフ化

gnuplotを使用して、先ほど作成したphoto.datをグラフ化する。 まず、描画の設定ファイルを用意する。

$ cat photo.plt

set grid                    # 格子線を描画
set xrange [0:150000]       # X軸の描画範囲
set yrange [400:800]        # Y軸の描画範囲
plot 'photo.dat' with line  # photo.datを読み込み線グラフを描画
set terminal png medium     # 画像の出力形式をpngに設定
set output 'photo.png'      # 出力ファイル名を設定
replot                      # グラフ画像をファイルに保存する。

上記の設定ファイルを引数としてgnuplotを実行するとグラフが描画される。

$ gnuplot photo.plt

出力された画像

photo.png
photo.png

なお、gnuplotを使ったグラフの詳細な設定方法や応用例などは、以下のURLを参照するとよい。

応用例

以下は、10カラム目の光センサのデータを情報を取り出し、最大値、最小値を求めるスクリプトである。

ソースリスト

class checkMinMax {
    static void main(args) {
        int min = 65536;        int max =     0;
        def f = new File(args[0])
        f.eachLine { line ->
            if ('T' != line.charAt(0)) {
                def column = line.split(",")
                int n = Integer.decode(column[9]).intValue()
                if (min > n      ) min = n
                if (      n > max) max = n
                println(column[0] + ", " + column[9])
            }
        }
        println("min:" + min + ", max:" + max)
    }
}

実行

$ groovy checkMinMax.groovy 20130613_150517.csv
0, 619
4, 618
8, 619

 .......
 .......

137593, 612
137597, 612
137601, 611
min:507, max:712

このスクリプトを拡張していけば、平均値、標準偏差などの算出に応用できるはずである。
各員プログラムの奥義を極め、CS大会に向けて一層奮闘努力せよ!

大切なこと