DPCデータの分析とかやるブログ

DPCデータの分析なんかをテキトーにやってます。

Scalaでcsvをいじってみました

最近Scalaをいじっています。
いえ、嘘をつきました。2ヶ月くらい断続的にいじってました。
遊び半分でいじっていたので、全然進んでいませんが、とても面白いですね。
ScalaJavaと同じ、JVMで動く言語です。そのため、コンパイルした結果はそのまま(Javaが走る環境ならどこでも)走ります。
今時はJavaが入ってないマシンの方が珍しいので、事実上どこでも動くと言って良いでしょう。

試しに書いてみる

先週は、PowerShellを使って「EF/Dファイルの退院年月日'00000000'を置換する」スクリプトを書きました。
Powershellでは驚くほど単純に書けましたが、Scalaだとこんな感じです。

package example

object ModifyEF extends helperfunc with App {

import java.io.FileReader
import collection.JavaConversions._
import com.opencsv.CSVReader
import com.opencsv.CSVWriter
import java.io.FileWriter
import scala.collection.JavaConverters._


val reader = new CSVReader(new FileReader("edata.txt"),'\t')
val test = reader.readAll.toList

val changed = test.transpose.map(matchlist(_))
val writing = changed.transpose.map(_.toArray)

val writer = new CSVWriter(new FileWriter("out.txt"), '\t')
writer.writeAll(writing.asJava)
writer.flush


}

trait helperfunc {
def changenull(list:List[String]):List[String] = {
    list.map({case "00000000" => "infinity"; case x => x})
}

def matchlist(list:List[String]):Array[String] = {list.head match {
    case "退院年月日" => changenull(list).toArray
    case _ => list.toArray
}}

}

うーん、ぱっと見恐ろしく見えますね。
csvの読み込み操作をワンライナーで済ましてくれる、Pandasのpd.read_csv()とか、PowerShellImport-Csvなんかはありません。
JavaのFileReaderを利用してファイルを読み込み、それをCSVReaderでパースする、という処理を明示する必要があります。
ですが、ここで使われている外部ライブラリはCSVのパースに使うopencsvだけです。
他は全てScala / Javaの標準ライブラリです。
速度はPandasのコードとそう大差ありませんし、PowerShellの例よりはずっと高速です。
しかもこれはScalaJavaも全然わかってない人間の書いた、最初のコードですから、きっと高速化する余地がありますね!
(注:つまり、このコードはとんでもない基本的な大間違いをしている可能性が存分にあり、かつ、ひどいメモリ使用・誤った考え方を含む可能性が高いです)
配布するのに苦労が無いので、ちょっとしたツールはScalaで書いてjarファイルで公開するかも知れません。
そこまでたどり着けるかどうか不明ですが・・・