lhae-0.0.2: src/Controller/Menu/Statistics/Descriptive.hs
module Controller.Menu.Statistics.Descriptive (eventHandler)
where
import Prelude hiding (max,min)
import Control.Monad (foldM,forM_,when)
import Control.Applicative ((<$>))
import Data.Maybe (catMaybes)
import Controller (Controller,onView,onGridView,onGridModel)
import qualified Controller.Grid as Grid
import Controller.Dialog (nonNumericDataWarning)
import Controller.Menu.Table.Add (addColumn)
import Controller.Canonical (addRow)
import Util (justWhen)
import Model.Grid (getColumnValues)
import Model.CellExpression.Evaluator.Common (getNumList)
import qualified Model.CellExpression.Evaluator.Math as Math
import View.Component.Grid (getColumnLabel,getColumnLabels)
import View.Dialog.Complex (Layout (..),Widget (..),Modifier (..)
,showSimpleDialog,okButton,cancelButton)
import I18n (__)
data Parameters = Parameters { columns :: [Int]
, calcMean :: Bool
, calcMedian :: Bool
, calcStdDeviation :: Bool
, calcMax :: Bool
, calcMin :: Bool
}
data Descriptive = Descriptive { label :: String
, mean :: Maybe Double
, median :: Maybe Double
, stdDeviation :: Maybe Double
, max :: Maybe Double
, min :: Maybe Double
}
type Result = ([String],[Descriptive])
eventHandler :: Controller ()
eventHandler = do
labels <- onGridView getColumnLabels
params <- onView $ showSimpleDialog (__ "Descriptive Statistics")
(dialog (__ "Columns") labels) $ Parameters [] True True True True True
justWhen params calcDescriptiveTable
dialog :: String -> [String] -> Layout Parameters ()
dialog labelsCaption labels =
let setColumns p cols = p {columns = cols}
setCalcMean p b = p {calcMean = b}
setCalcMedian p b = p {calcMedian = b}
setCalcStdDev p b = p {calcStdDeviation = b}
setCalcMax p b = p {calcMax = b}
setCalcMin p b = p {calcMin = b}
in
Modifier Margin $ Column
[ Row [ Grid
[[ Label $ __ "Mean"
, Widget $ CheckBox "" calcMean setCalcMean]
,[ Label $ __ "Median"
, Widget $ CheckBox "" calcMean setCalcMedian]
,[ Label $ __ "Standard Deviation"
, Widget $ CheckBox "" calcStdDeviation setCalcStdDev]
,[ Label $ __ "Maximum", Widget $ CheckBox "" calcMax setCalcMax]
,[ Label $ __ "Minimum", Widget $ CheckBox "" calcMin setCalcMin]]
, Modifier (Boxed labelsCaption)
$ Widget $ MultiListBox labels columns setColumns]
, Modifier Center $ Row [okButton (),cancelButton]]
calcDescriptiveTable :: Parameters -> Controller ()
calcDescriptiveTable params = do
(invalidCols,result) <- foldM (descriptive params) ([],[])
$ columns params
when (not $ null result) $
do Grid.new Nothing
when (calcMean params) $ addColumn $ Just $ __ "Mean"
when (calcMedian params) $ addColumn $ Just $ __ "Median"
when (calcStdDeviation params) $ addColumn $ Just $ __ "Standard Deviation"
when (calcMax params) $ addColumn $ Just $ __ "Maximum"
when (calcMin params) $ addColumn $ Just $ __ "Minimum"
forM_ (reverse result) $ \desc ->
do addRow (Just $ label desc,descriptiveToRow desc)
when (not $ null invalidCols)
$ nonNumericDataWarning $ reverse invalidCols
descriptive :: Parameters -> Result -> Int -> Controller Result
descriptive params (invalidCols,xs) col = do
colLabel <- onGridView $ getColumnLabel col
result <- getNumList <$> (onGridModel $ getColumnValues col)
case (result) of
Left _ -> return (colLabel : invalidCols,xs)
Right values ->
let calculate condition v = if condition params
then Just v else Nothing
mean = calculate calcMean $ Math.mean values
median = calculate calcMedian $ Math.median values
stdDev = calculate calcStdDeviation $ Math.stdDeviation values
max = calculate calcMax $ maximum values
min = calculate calcMax $ minimum values
in
return ( invalidCols
, Descriptive colLabel mean median stdDev max min : xs
)
descriptiveToRow :: Descriptive -> [String]
descriptiveToRow desc =
map show $ catMaybes [ mean desc
, median desc
, stdDeviation desc
, max desc, min desc
]