Haskell でヒストグラムを作るにはどうすればいいかを考えてみた。
まずはデータの作成から。サイコロを2つ振った時の出た目の合計のリスト scores を作った。 Prelude> let scores = [x + y | x <- [1..6], y <- [1..6]] Prelude> scores [2,3,4,5,6,7,3,4,5,6,7,8,4,5,6,7,8,9,5,6,7,8,9,10,6,7,8,9,10,11,7,8,9, 10,11,12] scores の最小値と最大値を求めた。 Prelude> let smin = minimum scores Prelude> smin 2 Prelude> let smax = maximum scores Prelude> smax 12 ヒストグラムの区間の幅を 1 にした。 Prelude> let binWidth = 1 データの最小値と最大値が収まるような区間を求めた。 Prelude> let bins = [smin, (smin + binWidth)..(smax + binWidth)] Prelude> bins [2,3,4,5,6,7,8,9,10,11,12,13] 区間の境界値の組を作った。 Prelude> let intervals = zipWith (\x y -> (x,y)) (init bins) (tail bins) Prelude> intervals [(2,3),(3,4),(4,5),(5,6),(6,7),(7,8),(8,9),(9,10),(10,11),(11,12),(12,13)] x が区間 u 内に入っているかどうかを判別する関数 within を作った。 Prelude> let within u x = x >= fst u && x < snd u Prelude> within (3,4) 3 True scores の中で (5,6) の中に入っている値を取り出した。 Prelude> filter (within (5,6)) scores [5,5,5,5] 全ての区間で上と同じ事をやった。 Prelude> map (\u -> filter (within u) scores) intervals [[2],[3,3],[4,4,4],[5,5,5,5],[6,6,6,6,6],[7,7,7,7,7,7],[8,8,8,8,8],[9,9,9,9],[10,10,10],[11,11],[12]] 出現頻度を数えた。 Prelude> map length $ map (\u -> filter (within u) scores) intervals [1,2,3,4,5,6,5,4,3,2,1] 区間とペアにした。 Prelude> zip intervals $ map length $ map (\u -> filter (within u) scores) intervals [((2,3),1),((3,4),2),((4,5),3),((5,6),4),((6,7),5),((7,8),6),((8,9),5),((9,10),4),((10,11),3),((11,12),2),((12,13),1)] ghci で試行錯誤しながら作れるので、頭が疲れない。 そこで、これらをまとめて関数 histogram を作ってみた。開発はボトムアップで行ったが、それをもとに histogram はトップダウンで開発する。Haskell では関数はどの順序で記述してもいいので余計な配慮が要らないのが楽だ。ボトムアップで開発してトップダウンで記述するといっても、関数の定義を単に並べ替えるだけでプログラミングができてしまう。やってみると分かるが、すごくうれしい。 ファイル名: test.hs histogram leftmost binwidth rawdata = zip intervals $ map length $ map (\u -> filter (within u) rawdata) intervals where intervals = zipWith (\x y -> (x,y)) (init bins) (tail bins) bins = [leftmost, (leftmost + binwidth)..(smax + binwidth)] smax = maximum rawdata within u x = x >= fst u && x < snd u 実行例: *Main> let scores = [x + y | x <- [1..6], y <- [1..6]] *Main> histogram 2 1 scores [((2,3),1),((3,4),2),((4,5),3),((5,6),4),((6,7),5),((7,8),6),((8,9),5),((9,10),4),((10,11),3),((11,12),2),((12,13),1)] 実用的に使うためには、数値の型にも配慮しないといけないが、それは宿題ということで。
by tnomura9
| 2012-07-04 18:52
| Haskell
|
Comments(0)
|
カテゴリ
新型コロナウイルス 主インデックス Haskell 記事リスト 圏論記事リスト 考えるということのリスト 考えるということ ラッセルのパラドックス Haskell Prelude Ocaml ボーカロイド 圏論 jQuery デモ HTML Python ツールボックス XAMPP Ruby ubuntu WordPress 脳の話 話のネタ リンク 幸福論 キリスト教 心の話 メモ 電子カルテ Dojo JavaScript C# NetWalker ed と sed HTML Raspberry Pi C 言語 命題論理 以前の記事
最新のトラックバック
最新のコメント
ファン
記事ランキング
ブログジャンル
画像一覧
|
ファン申請 |
||