2005年11月29日 火曜日

はてなブックマーク - なんでもかんでもExcel症候群

気がついたらこんな所にリンクを貼られてしまっているとは… 世の中恐ろしいものだ。今のところこの日記はblog的な要素(trackbackとかcommentとか)を持っていないことと、サーバの引っ越しをしたときに実行環境の差でBBSが動かなくなってしまったので、読んだ人の意見が取れない・・・(BBS自身は入れ替えたいけど、時間がねえ。) ちょっと悲しいが、まぁ良いか。
統計関係のワークシート関数のうちよく使うものだけは何とかしたいものだなあ・・・

2005年11月24日 木曜日

続・なんでもかんでもExcel症候群

Unixな機械からテキストファイルを直接持ってくると、改行がWindowsと異なるので、Excelで扱うのがちょっとめんどくさい。FTPできるときは、ASCIIで持ってくればDOS/Windowsなテキストファイルになるのだけど、世の中FTPできなくて専用のクライアントを共用されることもあって涙が出てくることがもうしょっちゅうあって困る。で、そんな_だめだめクライアント_に泣く泣くつきあわなければならないのだが、この際_なんでもかんでもExcelにお任せ_なのだ。
これからはASCIIモード転送のことは忘れて、すべてBINARYモード転送にしてしまいましょう。DOS/Windowsの世界ではUnixで作成したテキストは何行あっても、_たった1行のテキストファイル_と見なせるから、これを全部1つの文字列に取り込んで、ばらす方向で考える。ソースを示す。

Sub TextRead(FileName As Variant)
' TextReadプロシジャ: FileNameで指定されたファイルを読み込む
' FileName: 入力するファイルのファイル名
    Dim RE As Object
    Dim StreamString As String
    Dim textlines As Object
    Dim textline As Object
    Dim tmp(2) As String
    Dim myDate As Date
    Dim PATTERN as String
    Set RE = CreateObject("VBScript.RegExp")
    
    With RE
        .Pattern = ".+\n"
        .IgnoreCase = False
        .Global = True
    End With
    Open FileName For Input As #1
    Line Input #1, StreamString
    Close #1
    
    Set textlines = RE.Execute(StreamString)
        
    For Each textline In textlines
                
	' textlineはUnixにおける行と同じ。ここに処理したいことを書く
    
    Next
    
    Set RE = Nothing
End Sub

こんなことをやると、textlinesコレクションに入る各要素はUnixで言うところの行の集合、その要素は行と同じものになったりします。Executeメソッドって便利だねぇ。イメージ的にはperlやrubyでやっているストリームに対するwhileループのようなことができるのだけど若干表現が冗長。VBAで可変長Stringはヘルプによると2GBまで取れるらしいので、まぁ普通のテキストファイルの処理をする場合は一つのファイルを1つの文字列に取り込んで処理して何の問題もないだろう。そんなわけで、Unixからファイルを持ってきてExcelでごにょごにょするときはASCII転送しちゃいけません。BINARY転送でOK。
さらに()を用いてグループ化した正規表現を書いて括弧にマッチした文字列を抽出したいのだけどどうするか? これも簡単。めんどくさいのでこんなプロシジャを書いておこう。

Public Sub REGetValue(ByVal Pattern As String, ByVal Stream As String, ParamArray Args())
' REGetValueプロシジャ: 正規表現Patternの中で()を用いてグルーピングされた値を抜き出す
' Pattern: 正規表現
' Stream:  検索を行う文字列
' Args:    パターンマッチした値を格納する変数
    Dim RE As Object
    Dim Results As Object
    Dim Result As Object
    Dim i As Integer
    
    Set RE = CreateObject("VBScript.RegExp")
    With RE
        .Pattern = Pattern
        .IgnoreCase = False
        .Global = True
    End With
    
    Set Results = RE.Execute(Stream)
    For Each Result In Results
        
        For i = LBound(Args) To UBound(Args)
            Args(i) = Result.SubMatches(i)
        Next i
    
    Next Result
    Set RE = Nothing
    
End Sub

パターンとマッチした文字を入れる変数を渡すと、パターンマッチを行って変数にマッチした文字を入れるプロシジャーだ。変数の個数は可変長で与えられる。正規表現が間違っているときや、個数があわないときは何か変なことが起こるかもだけどもその辺は適当に例外処理するなり、エラー処理するなり考えよう。(そんなところまで書いてられないわい。) とりあえず正規表現周りはこの辺でおしまい。あとはフクロウ本を読みましょ。

もっと読む

2005年11月23日 水曜日

勤労感謝の日

今日は世間的には「勤労感謝の日」なのだが、僕の勤労を感謝してくれるような人なんていやしない。 働いていく上で襲いかかってくるのは、最近はソフトウェアなことしかやってないから、_ソフトウェア特許_とか_アイディア特許_だとかいった考えるだけでもうんざりするようなことしかありゃしない。ちなみに勤労感謝の日は皇室の新嘗祭にちなんだ祝日なので、_一般庶民の勤労を感謝している_と言う日ではないことを忘れちゃならない。

竹澤 邦夫 / みんなのためのノンパラメトリック回帰(上) 第2版

最近ちょっとした解析で導関数も必要な信号補間を行うことになったのだが、ずっと昔に研究室の先輩が平滑化スプラインを用いた補間を行っていたなあと言うことをを思い出した。あの当時はMS-DOSで動かしていたこともあって、いろいろな制約(補間処理をするのにデータを間引いていたとか、確実に配列が1セグメントよりでかくなるので)があったし、当時のPCの計算能力だと結構いい時間がかかっていた。今時のPCだと数秒かなと思い立ち調べてみた。
学生の頃平滑化スプラインの日本語の文献は、「Cによるスプライン関数—データ解析 CG 微分方程式」くらいしかなかったように思うのだが、ここ10年のコンピュータの高速化もあって、この手の解析法(ノンパラメトリック回帰というらしい)はずいぶんポピュラーになったようです。で、さらに調べてみることにした。
そうするとRのGeneral Smoothing Splines(gss) Packageと言う何ともそのものズバリなものを発見。(statsパッケージにもsmooth.splineというオブジェクトがあって、こっちは補間値を出すときに導関数の階数を指定できる。) 「Rによるノンパラメトリック回帰」という文書を参照にやってみるとなかなか良さそうである。ただこれを見ただけだと何をやっているのか、おぼろげにしかわからないので、どうしたものかと思っていたところ、この文章を書かれた竹澤さん自身の著書であるみんなのためのノンパラメトリック回帰(上) 第2版に行き着いた。
この本は受注生産らしく、Amazonで購入してみたのであるが、最初1ヶ月くらいかかるような通知であった。厳しいなぁと思っていたら、翌日に_発想しました_と言う通知があって、びっくり。最初のメールは何だったんだろう。で、昨日の夜に入手となったわけだ。とりあえず1章を斜め読み。今まで読んだ統計関係の本の中では_異色の素晴らしくおもしろい本であると思う_。ざっくり今までのオーソドックスな多変量解析をやっていた人の心に突き刺さる項目を列挙してみよう。

  • 移動平均やフーリエ級数でいいのだろうか
  • ヒストグラムや正規分布で良いのだろうか
  • 補間で良いのだろうか
  • 正しい式を使えばいいのだろうか
    第一章はこんな項目で、項目だけ列挙してもかなりおもしろいのである。ヒストグラムを書くときに区切り幅や端点をどう選んでいるだろうか? 果たして正規分布になっているのだろうか? (扱っている系は中心極限定理を満たすようになっているのだろうか?) 曲線を求めるときに実験的な誤差を考えているだろうか? というようなところでふむふむと思っていたのであるが…
    1.5節の 「正しい式を使えばいいのだろうか」と言う項目は確かに凄い内容を含んでいる。僕は物理出身の人間なので、実験で得られる値は、より基礎的な方程式(運動方程式とかMaxwellの方程式とかから導出された方程式を満たす物として、そのモデル式を回帰解析で当てはめるのであるが、この節は_それが本当に正しいのか_という究極の問いを突きつけているように感じられる。神のみぞ知る方程式よりも、その現象を言い当てる全く別の関数が存在すると言う話なのであるが、よく考えれば自在曲線定規の形状は既知の関数形だろうか? もし統計的に意味ある扱いで自在曲線定規のような曲線(これが平滑化スプラインなのであるが)を書ければ有用かもしれない。
    ということで、がんばって下巻まで読んでみようと思うのだけど。この本は受注生産だけあって、印刷品質が・・・ TeXで書かれているので、もっと綺麗に仕上げることができそうだと思うのだが、まぁそこは仕方ないか。数式が読みやすいので良しとしよう。

プリンター修理

我が家のプリンターであるが、ここ最近写真印刷をするとすじ状の模様が発生する。先々週の週末に年賀状シーズンが近いことと、保証期限が今月いっぱいであることを思い出して、修理に出した。ヘッド交換になって帰ってくるだろうという予想であったが、月曜日に修理完了という報告があったので引き取りに出かけた。予想通りの修理内容であった。持ち帰って何枚かプリントしたが、不具合点は解消したようである。それにしても印刷している写真の色域から考えてほとんど使われない赤と緑のインクはヘッドクリーニングだけで使い切ってしまった・・・

BBS不具合

月初めにうちのコンテンツのサーバ移動を行ったのであるが、それ以来BBSが不調(日記も不調だったのだが、これは原因がわかったので直した)。原因の追及がめんどくさいので、新しくBBSのCGIを探してくるかなあ…

もっと読む

2005年11月22日 火曜日

なんでもかんでもExcel症候群

何でもかんでもPowerPoint症候群の弊害を日記で書いたのだが、それよりも世の中に広く広まっている病的な物と言えば、_なんでもかんでもExcel症候群_であろう。とにかく通常の表だけに飽きたらず、提出書類から報告書まで_何でもかんでもExcel_なのである。つまり「何でもかんでもExcel症候群」とはExcelだけですべての仕事が完結してしまう恐ろしい病気なのだ。
その病巣の由来を簡単に予想するとすれば、子供の頃に升目の入ったノートで漢字の書き取りをやらされ(つまりカーニングとかに無頓着になる)、読書感想文などの類は原稿用紙で書かされ、漢字は少ない文字数で情報量を詰め込めることからすっきりとした表が書きやすく、何でもかんでも_表にしないと気が済まない_という日本人の悲しい習性に由来する物であろうと思うのだ。
まぁUnixでEmacsしか使わないというのと似たような話ではあるのだが、典型的なEmacsユーザーが扱うのは汎用的なテキストファイルであり、Emacs LISPでがんがんプログラムを書く(設定ですらLISPを書かねばならないので、多少は誰でも書く物だ)人が多い用に思われる。Excelの場合は、XLS形式という特殊なフォーマット(最近のはXMLなのか?)を用い、適当なワークシート関数などを表層的に使いこなしている人が多く、Excelの基本技とも言えるピボットテーブルとかソルバーを使いこなしている人がどの程度いるかと問えば、結構怪しい物だ。
まぁ会社で働いているとこういう病的な世界と常に隣り合わせであり、いつも精神汚染を受けているのであるが、これを前向きに楽しむにはどうすればいいか? ということに焦点を絞り込んで生活しないとやってられないと言うことになるであろうか。
そんなわけでExcelをちゃんと使いこなすにはVBAで遊びまくればいいのであるが、テキストファイルとのつきあいもやめられない。Unixな環境に一度でも触れてしまうと、VBAのお気軽さを楽しんでいても感じる最大の問題点は_正規表現が使えない_と言うところがなやましい。これまで正規表現(とハッシュ)を使うためにVBAからだと駄目だと思い、Active PerlとかActive Rubyとか非VBAでCOMオブジェクトをさわれる言語を選択していたのであるが、書いたプログラムを使ってもらうのに_わざわざPerlだのRubyだのをインストールしてもらわねばならない_という痛い問題があった。Windowsで全然閉じていないのである。Mac OSXみたいにPerlとかRubyがインストールされていればこんなことは考えなくて良いのだが、PerlやRubyを使うのは_Windows的なやり方ではないのである_と言う結論に落ち着いた。
Windows的にどうすればいいのかと言う話なのだが、結局のところ現在のほぼすべてのオフィスにあるWindows環境で前提として良さそうな物は、Internet Explorer 6 SP2とExcelであろうと言うことになる。いろいろ調べているとIE5以降だと、WIndows Scripting Hostが使える。_まてよWSHにはたしか正規表現オブジェクトがあったぞ_と思い出して、さらにCOMで呼び出せるじゃんと言うことを思い出したので、一気にこの方面の悩みが解消した。要はWSHの正規表現オブジェクトをVBAのオブジェクトにしてしまえばいいのである。なんてこったい。こんなので数年悩んでたよ。とりあえず、あるディレクトリにある複数のファイルを選択して、そのすべてのファイルに、入力したパターンマッチをして置換を行うVBAプログラムを書いてみよう。

Option Explicit
' RESample Programed by Kentaro OGAWA <kentaro@nn.iij4u.or.jp>
Public Sub RESample()
    
    ' 変数の宣言
    
    Dim RE As Object
    Dim Filenames As Variant
    Dim FileCount As Integer
    Dim OutputFile As String
    Dim StreamString As String
    Dim Pattern As String
    Dim ReplaceString As String
    
    '正規表現オブジェクトの準備
    Set RE = CreateObject("VBScript.RegExp")
    
    Pattern = InputBox("検索パターンを入力")
    ReplaceString = InputBox("置換文字列を入力")
    
    With RE
        .Pattern = Pattern
        .IgnoreCase = False
        .Global = True
    End With
    ' 処理ファイルの選択
    Filenames = Application.GetOpenFilename _
        (FileFilter:="すべてのファイル(*.*), *.*", _
        Title:="必要なファイルを選択して,「開く」ボタンを選択してください。「カンマ (,)」と「コロン (:)」で区切ります。", _
        MultiSelect:=True)
    If IsArray(Filenames) = False Then
    
        If Filenames = False Then
            MsgBox "「キャンセル」ボタンを選択しました"
        End If
    
    Else
    
        For FileCount = 1 To UBound(Filenames)
            
            OutputFile = Filenames(FileCount) + ".new"
            
            Open Filenames(FileCount) For Input As #1
            Open OutputFile For Output As #2
            
            Do While Not EOF(1)
            
                Line Input #1, StreamString
                Print #2, RE.Replace(StreamString, ReplaceString)
                
            Loop
            Close #1, #2
            
        Next FileCount
    
    End If
    Set RE = Nothing
End Sub

こんな感じでいいのかねえ。まぁ普通にExcel VBAをやっている人は結構見かけるのだけどちゃんとファイル入出力を書いている人は見たことがないのだが… Rubyとかでやれば数行のプログラムなのであるが、VBAでやるとかなり冗長だ。まぁPaul Grahamが言うところの_力のない_言語なのでその辺は見切りが必要。
まぁExcelを使っている人でファイル入出力で正規表現を使う人は似非である。典型的な「なんでもかんでもExcel症候群」の人の基本は、セルに読み込んで一個ずつ検索し、データの出し入れは2次元ポインタと見なして、_値の記憶とかの操作はCell関数をつかってセル単位で行い、ワークシート関数を使う_ってやるって言うものだ。僕はポインターがわからないのでExcel使いじゃありません。(上のソースも別にWordのマクロとしても動くのを忘れてはいかん。ついでにほぼそのままVB6でも動く。試してないが。ちなみにExcelVBAでみる変態的なポインタの使い方がわからんだけで、毎日C++でSTLは使い込んでますよ。)
この道はまだまだ深いので次回に続く。まったくちょっと調べただけで、VBAスキルが20くらいあがってしまったぞ…

もっと読む

2005年11月17日 木曜日

「アルゴリズム+データ構造=プログラム」? 本当に?

福盛さんのプログラミングにおけるインターフェイスに関する考察。なかなか興味深く読ませていただいた。構造化の要件としての「アルゴリズム」と「データ構造」に加えて、プログラムになるには「インタフェース」も必要なのではないかという話。面白い視点だとは思うのだけど、はたしてそうなんだろうか?
プログラムという概念を考える際に人によってその規模が違うので、たしかに「アルゴリズム+データ構造=プログラム」というのは必ずしも自明ではない。(僕自身は「Σ(アルゴリズム×データ構造)=プログラム」ではなかろうかと思うのだけれども。) たとえば数行で記述可能な簡単なものから、Officeソフトのような大規模なものまで、どれもプログラムである。プログラムというものをどういうくくりで考えればいいのだろうか? 小規模なプログラムについては「アルゴリズム+データ構造=プログラム」と言う直感的な理解も可能であるが、福盛さんの考察は、構造化・モジュール化を進めた大規模なプログラムとなるとどうであろうかという論点であると思う。
僕はそもそも等号が成り立つような次元が同じ物ではないので階層化して考えたほうが自然だと思う。インターフェースやプログラムという概念は、「アルゴリズム」や「データ構造」のようなプリミティヴな存在であるか否か?という視点でかんがえたいのである。僕は「インターフェース」は「アルゴリズム」や「データ構造」とは同じ次元の存在ではなく、「アルゴリズム」と「データ構造」というプリミティヴな概念を演繹したようなもので記述可能ではなかろうかと思う。(公理論的アプローチなのかもしれないが…)
ではインターフェースというものをどう言う位置付けでおいておけばいいのかという話になるのであるが、インタフェースはその名のとおり、振る舞い(応答? 動作?なんて言うのかな)・データ・プログラム・外界との_相互作用_を考えた際にはじめて登場する概念だから、第1層目としてはアルゴリズム・データ構造、第2層目は第1層目の概念のみで記述可能であるインターフェース・プロシジャ・オブジェクト・プログラムというような階層的な理解でいいんじゃなかろうか? (プログラムを3階層目において置いた方がいいかな・・・整理悪いかも。)
ただしこれはプログラムの構成要素としてボトムアップして考えてみただけであって、実際のところプログラムが何でできているのかを考える際には実装詳細はどうでも良くて、インターフェースとその振る舞いが規定されていれば良いだけのような気がする。あとあの本はインターフェース云々以前の時代の本で、現代的なプログラミングとは若干の差があるのはあたりまえと思う。あくまで手続き指向な言語から構造化プログラミングへプログラミング・スタイルを切り替える提案をした本だという理解をすべきかと思うのだけど。ちゃんと読んでないから、なんとも。(Adaの本とかも今読むとふむふむと思うところはあるんだよねえ。Pascalに型総称性をいれてがちがちな仕様にしたらAdaになりそうだもんなあ。ただAdaにしてもPascalにしても好きではないな。)

日記の補完をせねば

今月は忙しくてあまり日記を書いてません。ネタはあるので、さかのぼって補完することになりそうです。

もっと読む