Skip to content

Pareto Chart #423

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
kMutagene opened this issue Sep 22, 2023 · 6 comments
Closed

Pareto Chart #423

kMutagene opened this issue Sep 22, 2023 · 6 comments
Labels
Difficulty: Beginner Hackathon projects with beginner difficulty FsLab Hackathon 2023 Implementation projects for the 2023 FsLab Hackathon Status: In Progress

Comments

@kMutagene
Copy link
Collaborator

kMutagene commented Sep 22, 2023

Description

A Pareto chart is a type of chart that contains both bars and a line graph, where individual values are represented in descending order by bars, and the cumulative total is represented by the line. The chart is named for the Pareto principle, which, in turn, derives its name from Vilfredo Pareto, a noted Italian economist. [1]

Example:

Pointers

  • Ideally, you start prototyping in a scripting or notebook environment where you can iterate fast. installation instructions can be found here: https://plotly.net/#Installation
  • Charts like this that are using baseline trace types to create a new chart type should only be implemented in the top-level Chart API. An example where this is already done is the Range chart that combines a set of differently styled line charts.
  • When possible, use #IConvertible for data input, as this allows for strings, number types such as int and float, and DateTime.

References

@kMutagene kMutagene added Difficulty: Beginner Hackathon projects with beginner difficulty FsLab Hackathon 2023 Implementation projects for the 2023 FsLab Hackathon Status: Available labels Sep 22, 2023
@kMutagene kMutagene moved this to Status: Available in FsLab Hackathon 2023 Sep 23, 2023
@rockfaith75
Copy link
Contributor

I'm working on this

@bvenn bvenn moved this from Status: Available to Status: In Progress in FsLab Hackathon 2023 Sep 30, 2023
@kMutagene
Copy link
Collaborator Author

hey @rockfaith75 i think you worked on this together with @smoothdeveloper. Is one of you still planning to finish this? If not, I would greatly appreciate if you could link what you ended up with during the hackathon (e.g. a script or notebook you worked in) so others can use it as a foundation to tackle this chart. If also do not have anything to link, no worries, please just tell me that this issue is up-for-grabs again. Thanks ❤️

@rockfaith75
Copy link
Contributor

rockfaith75 commented Oct 19, 2023 via email

@kMutagene
Copy link
Collaborator Author

Hey @rockfaith75 cool that you are still working on this, take all the time you need.

I might be best reachable on the fslab discord server: https://discord.gg/k3kUtFY8DB

@smoothdeveloper
Copy link
Contributor

@kMutagene this is what we ended up playing with during the hackaton, in meantime it is useful to people lurking.

#r "nuget: Plotly.NET"
open Plotly.NET
open Plotly.NET.TraceObjects

let labelAndValues = [
    
    "Child Care"      , 44.8 
    "Public Transport", 27.2 
    "weather"         , 19.6
    "Traffic"         , 56.
]

module Seq =
    let unzip keyValues =
        keyValues |> Seq.map fst
        , keyValues |> Seq.map snd

type Chart with
    static member Pareto(keysValues: seq<string * float>, ?Name: string, ?Label: string) =
        let orderedLabels, orderedValues =
            keysValues
            |> Seq.sortByDescending snd
            |> Seq.unzip
        
        let sum = orderedValues |> Seq.sum
        let topPaddingRatio = 0.05
        let cumulativeSum = 
            Seq.scan (+) 0. orderedValues
             |> Seq.skip 1
        
        let paretoValues = 
            Seq.zip orderedLabels cumulativeSum
            |> Seq.map (fun (label,value) -> label, value / sum * 100.) 
        
        let bars = Chart.Column(Seq.zip orderedLabels orderedValues,?Name=Name)
        
        let points = 
            Chart.Point(
                paretoValues
                , ShowLegend = false
                , Marker     = Marker.init(Size = 8, Color = Color.fromKeyword Black, Symbol = StyleParam.MarkerSymbol.Cross, Angle = 45.)
            )
            |> Chart.withAxisAnchor (Y = 2)
            
        let lines = 
            Chart.Line(
                paretoValues
                , Name       = "Cumulative %"
                , ShowLegend = true
            ) 
            |> Chart.withAxisAnchor (Y = 2)
            
        [bars;lines;points] 
        |> Chart.combine 
        |> Chart.withYAxisStyle (
                ?TitleText = Label
                , Id       = StyleParam.SubPlotId.YAxis 1
                , ShowGrid = false
                , MinMax   = (0.,sum * (1.+topPaddingRatio))
            )
        |> Chart.withYAxisStyle (
                TitleText    = "%"
                , Side       = StyleParam.Side.Right
                , Id         = StyleParam.SubPlotId.YAxis 2
                , MinMax     = (0.,100. * (1.+topPaddingRatio))
                , Overlaying = StyleParam.LinearAxisId.Y 1
            )


Chart.Pareto(labelAndValues, Name="Budget", Label="$") |> Chart.show

I intend to work with @rockfaith75 in order to make a full fledged PR that will meet the bar for integration in the library.

@kMutagene
Copy link
Collaborator Author

This has been merged 🥳 , thank you @smoothdeveloper and @rockfaith75 !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Difficulty: Beginner Hackathon projects with beginner difficulty FsLab Hackathon 2023 Implementation projects for the 2023 FsLab Hackathon Status: In Progress
Projects
None yet
Development

No branches or pull requests

4 participants