packages feed

hgg-svg-0.1.0.0: examples/DfPlotDemo.hs

-- | api-guide 05-dataframe (DataFrame 連携) 用の図生成デモ。
--   ゼロ依存の Map ベース df を @(|>>)@ でバインドし、 列名だけで図を書く。
--
--   @cabal run df-plot-demo@ → @design/df-plot/*.svg@ を生成。
{-# LANGUAGE OverloadedStrings #-}
module Main (main) where

import           Graphics.Hgg.Backend.SVG (saveSVGBound)
import           Graphics.Hgg.Easy
import           Graphics.Hgg.Frame       ((|>>), BoundPlot, bpDiagnostics)
import           Data.Text                (Text)
import qualified Data.Map.Strict          as M
import qualified Data.Vector              as V
import           System.Directory         (createDirectoryIfMissing)

-- df の列値は ColData (NumData/TxtData)。 数値列・文字列列のヘルパ。
num :: [Double] -> ColData
num = NumData . V.fromList

txt :: [Text] -> ColData
txt = TxtData . V.fromList

out :: FilePath -> BoundPlot -> IO ()
out name = saveSVGBound ("design/df-plot/" <> name <> ".svg")

main :: IO ()
main = do
  createDirectoryIfMissing True "design/df-plot"

  -- 1 枚の df を用意 (Map Text ColData。 列名で参照する)
  let df = M.fromList
        [ ("x",     num [1,2,3,4,5,6,7,8,9,10])
        , ("y",     num [2.1,3.9,6.0,7.7,10.2,11.8,14.1,15.9,18.2,20.0])
        , ("size",  num [2,8,3,9,4,7,5,6,3,8])
        , ("group", txt (take 10 (cycle ["A","B"]))) ] :: M.Map Text ColData

  -- (a) 散布図 + group で色分け + size で大きさ (全部「列名」で指定)
  out "01-scatter-color-size" $
    df |>> ( layer (scatter "x" "y" <> colorBy "group" <> sizeBy "size" <> alpha 0.85)
           <> title "df |>> scatter (color/size を列名で)" )

  -- (b) 重畳: 散布図 + 折れ線 (同じ df の別列を別 layer に)
  out "02-overlay" $
    df |>> ( layer (scatter "x" "y" <> size 6)
           <> layer (line "x" "y" <> color (fromHex "#d62728") <> stroke 1)
           <> title "df |>> (scatter <> line)" )

  -- (c) facet: group 列で小分け
  out "03-facet" $
    df |>> ( layer (scatter "x" "y" <> colorBy "group" <> size 6)
           <> facet "group"
           <> title "df |>> scatter <> facet \"group\"" )

  -- (d) 棒グラフ: カテゴリ列 + 群 + position (dodge)
  let dfB = M.fromList
        [ ("cat", txt (concatMap (replicate 3) ["A","B","C"]))
        , ("grp", txt (take 9 (cycle ["x","y","z"])))
        , ("val", num [3,5,2, 4,1,6, 2,3,4]) ] :: M.Map Text ColData
  out "04-bar-dodge" $
    dfB |>> ( layer (bar "cat" "val" <> colorBy "grp" <> position PosDodge)
            <> title "df |>> bar <> color <> position PosDodge" )

  -- (e) Phase 26 A2: vector field (quiver)。 格子点 (x,y) に渦巻き風の場 (u,v) の矢印。
  let gridPts = [ (gx, gy) | gx <- [-3,-2..3], gy <- [-3,-2..3::Double] ]
      uOf x y = -y/3 - x/6        -- 回転 + 内向き
      vOf x y =  x/3 - y/6
      dfQ = M.fromList
        [ ("x", num [ x | (x,_) <- gridPts ])
        , ("y", num [ y | (_,y) <- gridPts ])
        , ("u", num [ uOf x y | (x,y) <- gridPts ])
        , ("v", num [ vOf x y | (x,y) <- gridPts ]) ] :: M.Map Text ColData
  out "05-quiver" $
    dfQ |>> ( layer (quiver "x" "y" "u" "v" <> color (fromHex "#1f77b4"))
            <> title "df |>> quiver \"x\" \"y\" \"u\" \"v\" (vector field)" )

  -- (f) Phase 26 A2: 同じ場を magnitude で連続色マップ (arrowColorByMagnitude)。
  out "06-quiver-magnitude" $
    dfQ |>> ( layer (quiver "x" "y" "u" "v" <> arrowColorByMagnitude <> arrowScale 1.2)
            <> title "df |>> quiver <> arrowColorByMagnitude (|u,v| -> viridis)" )

  -- バインド時の列名検証 (純関数・例外なし。 診断は値として載る)
  let bad = df |>> layer (scatter "x" "wieght")   -- typo
  putStrLn ("診断 (typo 列): " <> show (bpDiagnostics bad))

  putStrLn "wrote design/df-plot/*.svg (6 examples)"