F# charting example

2019-04-29 10:56发布

I would like to do some basic charting in F# using build in features or a free library. And I would be very very pleased with a very basic example of it, a pie chart if possible.

Example data :

[("John",34);("Sara",30);("Will",20);("Maria",16)] 

Where the ints are percentages to be represented in the pie.

I have recently installed VSLab and though I find a lot of 3D examples, I am only looking for a simple pie chart...

It is also fine to use excel features by the way, not free, but installed nevertheless..

标签: f# charts
4条回答
啃猪蹄的小仙女
2楼-- · 2019-04-29 11:10

It's easy to do "made in home" pie chart: open System.Drawing

let red = new SolidBrush(Color.Red) in
let green = new SolidBrush(Color.Green) in
let blue = new SolidBrush(Color.Blue) in
let rec colors =
  seq {
    yield red
    yield green
    yield blue
    yield! colors
  }


let pie data (g: Graphics) (r: Rectangle) =
  let vals = 0.0 :: List.map snd data
  let total = List.sum vals
  let angles = List.map (fun v -> v/total*360.0) vals
  let p = new Pen(Color.Black,1)
  Seq.pairwise vals |> Seq.zip colors |> Seq.iter (fun (c,(a1,a2)) -> g.DrawPie(p,r,a1,a2); g.FillPie(c,r,a1,a2))
查看更多
手持菜刀,她持情操
3楼-- · 2019-04-29 11:20

Originally I only tried to complement ssp's example here with a very simple windows form dialog which shows a pie. But trying this I found a bug in ssp's code: on the one hand Seq.pairwise operates on vals instead of angles and on the other hand it obviously doesn't consider that pie slices will be drawn beginning from start angle along sweep angle.

I corrected the bug, commented, rearranged, reformatted and renamed some things - and made it both #load-able in fsi.exe and compilable with fsc.exe:

#light
module YourNamespace.PieExample

open System
open System.Drawing
open System.ComponentModel
open System.Windows.Forms

(* (circular) sequence of three colors *)
#nowarn "40"
let red = new SolidBrush(Color.Red)
let green = new SolidBrush(Color.Green)
let blue = new SolidBrush(Color.Blue)
let rec colors =
    seq { yield red
          yield green
          yield blue
          yield! colors }

(* core function to build up and show a pie diagram *)
let pie data (g: Graphics) (r: Rectangle) =
    // a pen for borders of pie slices
    let p = new Pen(Color.Black, 1.0f)
    // retrieve pie shares from data and sum 'em up
    let vals  = List.map snd data
    let total = List.sum vals
    // baking a pie starts here with ...
    vals
    // scaling vals in total to a full circle
    |> List.map (fun v -> v * 360.0 / total)
    // transform list of angles to list of pie slice delimiting angles
    |> List.scan (+) 0.0
    // turn them into a list of tuples consisting of start and end angles
    |> Seq.pairwise
    // intermix the colors successively
    |> Seq.zip colors 
    // and at last do FillPies and DrawPies with these ingredients
    |> Seq.iter (fun (c,(starta,enda))
                     -> g.FillPie(c,r,(float32 starta)
                                     ,(float32 (enda - starta)))
                        g.DrawPie(p,r,(float32 starta)
                                     ,(float32 (enda - starta))))

(* demo data *)
let demolist = [ ("a", 1.); ("b", 2.); ("c", 3.);
                 ("d", 2.); ("e", 2.); ("f", 2.) ]

(* finally a simple resizable form showing demo data as pie with 6 slices *)
let mainform = new Form(MinimumSize = Size(200,200))
// add two event handlers
mainform.Paint.Add (fun e -> pie demolist e.Graphics mainform.ClientRectangle)
mainform.Resize.Add (fun _ -> mainform.Invalidate())
#if COMPILED
Application.Run(mainform)
#else
mainform.ShowDialog() |> ignore
#endif

Last but not least I want to mention two helpful hints I found useful

查看更多
你好瞎i
4楼-- · 2019-04-29 11:24

Here's something I smashed together using the Google Chart API, I hope the code is clear enough without further explanation:

//Built with F# 1.9.7.8
open System.IO
open System.Net
open Microsoft.FSharp.Control.WebExtensions
//Add references for the namespaces below if you're not running this code in F# interactive
open System.Drawing 
open System.Windows.Forms 

let buildGoogleChartUri input =
    let chartWidth, chartHeight = 250,100

    let labels,data = List.unzip input
    let dataString = 
        data 
        |> List.map (box>>string) //in this way, data can be anything for which ToString() turns it into a number
        |> List.toArray |> String.concat ","

    let labelString = labels |> List.toArray |> String.concat "|"

    sprintf "http://chart.apis.google.com/chart?chs=%dx%d&chd=t:%s&cht=p3&chl=%s"
            chartWidth chartHeight dataString labelString

//Bake a bitmap from the google chart URI
let buildGoogleChart myData =
    async {
        let req = HttpWebRequest.Create(buildGoogleChartUri myData)
        let! response = req.AsyncGetResponse()
        return new Bitmap(response.GetResponseStream())
    } |> Async.RunSynchronously

//invokes the google chart api to build a chart from the data, and presents the image in a form
//Excuse the sloppy winforms code
let test() =
    let myData = [("John",34);("Sara",30);("Will",20);("Maria",16)]

    let image = buildGoogleChart myData
    let frm = new Form()
    frm.BackgroundImage <- image
    frm.BackgroundImageLayout <- ImageLayout.Center
    frm.ClientSize <- image.Size
    frm.Show()
查看更多
姐就是有狂的资本
5楼-- · 2019-04-29 11:29

Old question, but technology changing.

in vs 2013, F# 3, and installing the nuget Package

 Install-Package FSharp.Charting

Add reference to:

    System.Windows.Forms
    System.Windows.Forms.DataVisualization

and with one line of code:

     Application.Run ((Chart.Pie data).ShowChart())

The following F# code generate the bie chart:

open System
open System.Windows.Forms
open FSharp.Charting

[<EntryPoint>]
let main argv =  
    Application.EnableVisualStyles()
    Application.SetCompatibleTextRenderingDefault false   
    let data =[("John",34);("Sara",30);("Will",20);("Maria",16)]      
    Application.Run ((Chart.Pie data).ShowChart())
    0

and you get the following chart:

enter image description here

查看更多
登录 后发表回答