FlexChart for WinForms
WinForms パレート図
WinForms のチャートタイプ > 統計チャート > WinForms パレート図

パレート図は、プロセスの問題を最も頻度の高いものから低いもの順でグラフィカルにまとめて表示します。 この図は、棒グラフと折れ線グラフの両方で構成されます。棒グラフの値は相対度数を降順にプロットし、折れ線グラフは累積度数のパーセント値をプロットします。パレート図は、データがいくつかのカテゴリに分かれ、一連の要素から最も重要な要素を強調する必要がある場合に特に使用されます。たとえば、品質管理、在庫管理、顧客苦情処理などは、パレート図が頻繁に使用される分野です。

WinForms パレート図

FlexChart を使用すると、範囲付きヒストグラムを任意の折れ線グラフ、折れ線シンボルグラフ、またはスプラインシンボルグラフと組み合わせることで、簡単にパレート図を作成できます。まず、相対度数を範囲付きヒストグラムで降順にプロットします。次に、元のデータから累積相対度数のパーセント値を計算し、もう 1 つの系列を作成して、折れ線グラフ、スプライングラフ、折れ線シンボルグラフ、スプラインシンボルグラフのいずれかでプロットします。これがパレート図の折れ線グラフになり、各カテゴリが累積値に寄与する程度がわかりやすくなります。

private void Form1_Load(object sender, EventArgs e)
{
    this.flexChart1.ChartType = ChartType.RangedHistogram;
    var histogram = new C1.Win.Chart.RangedHistogram()
    {
        Binding = "Value",
        BindingX = "Name",
        Name = "Count",
        SortDescending = true,
        DataSource = GetPurchaseFactorsData(),
        DataLabel = new DataLabel { Content = "{y:N0}", Position = LabelPosition.Top },
    };
    this.flexChart1.Series.Add((Series)histogram);
    // パレート図のデータを計算します
    var histoYs = histogram.GetValues(0);
    var sum = histoYs.Sum();
    var paretoData = new List<PointF>();
    double cumulativeSum = 0;
    for (int i = 0; i < histoYs.Length; i++)
    {
        cumulativeSum += histoYs[i];
        paretoData.Add(new PointF
        {
            X = i,
            Y = (float)(cumulativeSum / sum),
        });
    }
    var paretoLine = new Series
    {
        Name = "Cumulative %",
        ChartType = ChartType.LineSymbols,
        DataSource = paretoData,
        Binding = "Y",
        BindingX = "X",
        AxisY = new Axis
        {
            Position = Position.Right,
            Min = 0,
            Max = 1,
            Format = "P0",
            Title = "Cumulative Percentage",
        },
    };
    this.flexChart1.Series.Add(paretoLine);
}
Private Sub Form1_Load(sender As Object, e As EventArgs)
    Me.flexChart1.ChartType = ChartType.RangedHistogram
    Dim histogram As RangedHistogram = New C1.Win.Chart.RangedHistogram() With {
          .Binding = "Value",
          .BindingX = "Name",
          .Name = "Count",
          .SortDescending = True,
          .DataSource = GetPurchaseFactorsData(),
          .DataLabel = New DataLabel() With {
              .Content = "{y:N0}",
              .Position = LabelPosition.Top
        }
    }
    Me.flexChart1.Series.Add(DirectCast(histogram, Series))
    ' パレート図のデータを計算します
    Dim histoYs As Double() = histogram.GetValues(0)
    Dim sum As Double = histoYs.Sum()
    Dim paretoData As List(Of PointF) = New List(Of PointF)()
    Dim cumulativeSum As Double = 0
    For i As Integer = 0 To (histoYs.Length - 1)
        cumulativeSum += histoYs(i)
        paretoData.Add(New PointF() With {
              .X = i,
              .Y = CSng(cumulativeSum / sum)
        })
    Next
    Dim paretoLine As Series = New Series() With {
          .Name = "Cumulative %",
          .ChartType = ChartType.LineSymbols,
          .DataSource = paretoData,
          .Binding = "Y",
          .BindingX = "X",
          .AxisY = New Axis() With {
              .Position = Position.Right,
              .Min = 0,
              .Max = 1,
              .Format = "P0",
              .Title = "Cumulative Percentage"
        }
    }
    Me.flexChart1.Series.Add(paretoLine)
End Sub

上記のサンプルコードは、GetPurchaseFactorsData という名前のカスタムメソッドを使用してチャートにデータを提供しています。要件に基づいてデータソースを設定できます。

Random rnd = new Random();
public List<CategoricalPoint> GetPurchaseFactorsData()
{
    var data = new List<CategoricalPoint>();
    for (int i = 1; i <= 7; i++)
    {
        int fact = 1;
        foreach (string factor in PurchaseFactors)
        {
            data.Add(new CategoricalPoint
            {
                Name = factor,
                Value = (22 - (fact * 3)) * rnd.Next(9, 15),
            });
            fact++;
        }
    }
    return data;
}
Private rnd As New Random()
Public Function GetPurchaseFactorsData() As List(Of CategoricalPoint)
    Dim data As List(Of CategoricalPoint) = New List(Of CategoricalPoint)()
    For i As Integer = 1 To 7
        Dim fact As Integer = 1
        For Each factor As String In PurchaseFactors
            data.Add(New CategoricalPoint() With {
                  .Name = factor,
                  .Value = (22 - (fact * 3)) * rnd.[Next](9, 15)
            })
            fact += 1
        Next
    Next
    Return data
End Function
Private _purchaseFactors As String()
Public ReadOnly Property PurchaseFactors() As String()
    Get
        If _purchaseFactors Is Nothing Then
            _purchaseFactors = GetObject("PurchaseFactors").ToString().Split("|"C)
        End If
        Return _purchaseFactors
    End Get
End Property
Private _dict As Dictionary(Of String, Object)
Private Function GetObject(key As String) As Object
    If _dict Is Nothing Then
        Dim json As String = File.ReadAllText("../../Data.json")
        Dim javaScriptSerializer As New JavaScriptSerializer()
        _dict = javaScriptSerializer.Deserialize(Of Dictionary(Of String, Object))(json)
    End If
    Return _dict(key)
End Function