Пример построения F # - PullRequest
       23

Пример построения F #

6 голосов
/ 28 ноября 2009

Я хотел бы сделать некоторые базовые графики в F #, используя встроенные функции или бесплатную библиотеку. И я был бы очень очень доволен очень простым примером этого, круговой диаграммой, если это возможно.

Пример данных:

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

Где целые числа - это проценты, которые должны быть представлены в круговой диаграмме.

Я недавно установил VSLab, и хотя я нахожу много 3D-примеров, я ищу только простую круговую диаграмму ...

Кстати, прекрасно использовать функции Excel, не бесплатно, но, тем не менее, установленные ..

Ответы [ 4 ]

8 голосов
/ 28 ноября 2009

Вот кое-что, что я разбил вместе, используя Google Chart API, Я надеюсь, что код достаточно ясен без дальнейшего объяснения:

//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()
3 голосов
/ 29 ноября 2009

Легко сделать круговую диаграмму "сделано дома": открыть 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))
2 голосов
/ 23 сентября 2016

Старый вопрос, но технология меняется.

в версии 2013, F # 3 и установка пакета nuget

 Install-Package FSharp.Charting

Добавить ссылку на:

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

и с одной строкой кода:

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

Следующий код F # генерирует контрольную диаграмму:

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

и вы получите следующий график:

enter image description here

1 голос
/ 10 октября 2011

Первоначально я только попытался дополнить пример ssp здесь очень простым диалоговым окном формы окна, которое показывает круговую диаграмму. Но, попробовав это, я нашел ошибку в коде ssp: с одной стороны Seq.pairwise работает на vals вместо angles, а с другой стороны, очевидно, что он не учитывает, что кусочки пирога будут нарисованы, начиная с начального угла вдоль угол развертки.

Я исправил ошибку, прокомментировал, переставил, переформатировал и переименовал некоторые вещи - и сделал так, что он #load может быть fsi.exe и скомпилирован с 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

И последнее, но не менее важное: я хочу упомянуть два полезных совета, которые я нашел полезными

  • в stackoverflow.com ответ ildjarn , где он показывает потрясающее (по крайней мере для меня) использование List.scan
  • в c-sharpcorner.com блоге Shalini Juneja , где она показывает, как создать и нарисовать простое диалоговое окно с изменяемыми размерами оконных форм с помощью F # (в факт, что она также показывает, как отобразить пирог)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...