【WPF】ScottPlot Ver 4.1 で楽々グラフ描画!旧Verとの違いも合わせて解説!

当ページのリンクには広告が含まれています。

個人的にはWPF用のグラフ作成ライブラリとして一押しのScottPlotですが、最近Pythonの記事に集中していたせいで、ScottPlot のバージョンアップをフォローしきれていませんでした。

以前のデモプログラムに最新版のScotPlot Nuget でインストールしたところ、結構仕様が変わっていて修正が必要でした。

そこで、今回は ScottPlot 4.1 用に書き直したデモプログラムの紹介と、 旧バージョン(4.0)との違いについて触れたいと思います。

尚、ScottPlot 4.1で本格的にグラフを描く上で必要な情報(軸タイトル指定、凡例、上限下限の設定、任意の文字列表示など)については、【WPF】いちばんやさしいScottPlot の使い方(WindowsForm共通)の記事でサンプルを公開しています。

ScottPlotで簡単にグラフを描画できるようにユーザーコントロール化もしていますので、コピペしてすぐに使いたい方は下記の記事をご活用下さい。

【WPF】C#+ScottPlotで折れ線グラフのユーザーコントロールを作る!
【WPF】ScottPlot 4.1でY2軸に対応した複合グラフのユーザーコントロールを作る!
【WPF】C#+ScottPlotで円グラフのユーザーコントロールを作る!

より深い情報が必要な際は、ScottPlotの公式ページに各グラフの画像とソースコードが掲載されていますので、こちらも参考にして下さい。

目次

デモプログラムの概要

今回のデモプログラムの画面は次の様になります。

タブが3つあって、各タブに4グラフ、合計12種類のグラフを表示します。

タブを切り替えることで、下記のグラフが表示されます。

ScottPlotの構造

ScotPlot は、ScottPlot.Plot でインスタンスを生成し、そのインスタンスに対して折線グラフや棒グラフを追加していきます。

各グラフの太さや色、表示する軸(X,Yども2軸まで表示可能)は、グラフのメソッドを読んだ時に返されるオブジェクトに対して行います。

plt = new ScottPlot.Plot(600, 400)
var sig = plt.AddSignal(DataGen.Sin(51, mult: 1));
sig.YAxisIndex = 0;
chart.Render();

ScottPlot 4.0 までは、グラフ作成メソッドに色や太さなどの引数があったのですが、ScottPlot 4.1 から上記の仕様変更が行われたため、引数がかなり省略されています。

下図は、ScottPlotクラスの内部構造のイメージ図となります。

ちなみに、デモプログラムでは ScottPlotをコントロールとして画面に張り付け、"uxChart" という名を付けており、この場合は以下のような記述になります。

plt = uxChart.Plot;
var sig = plt.AddSignal(DataGen.Sin(51, mult: 1));
sig.YAxisIndex = 0;
chart.Render();

ScottPlot 4.1 のインストール方法

今回は Visual Studio 2022 を前提とした解説になりますが、Visual Studio の過去バージョン(2019,2017)をお使いの方でも共通です。

まず、NuGetから「scottplot」というキーワードで検索し、「ScottPlot.WPF」を自分のプロジェクトにインストールします。

WindowsFormで利用されたい方は、その下の「ScottPlot.WinForms」をお選びください。

デモプログラムの紹介

参考までにデモプログラムのソースコードを公開しますが、ScottPlotは入っていません。

リビルドを行う場合は、事前にNuGetを使ってインストールをお願いします。

デモプログラムのソースコードダウンロードURL

デモプログラムのソースコードはこちらからダウンロードできます。

XAMLのソースコード

XAMLのソースコードは以下の通りです。

<Window x:Class="ScotPlotTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ScotPlotTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="1320">
    <Grid>
        <TabControl>
            <TabItem Header="チャート1">
                <Grid>
                    <WpfPlot x:Name="uxChart1" HorizontalAlignment="Left" Height="315" Margin="27,53,0,0" VerticalAlignment="Top" Width="300"/>
                    <WpfPlot x:Name="uxChart2" HorizontalAlignment="Left" Height="315" Margin="345,53,0,0" VerticalAlignment="Top" Width="300"/>
                    <WpfPlot x:Name="uxChart3" HorizontalAlignment="Left" Height="315" Margin="664,53,0,0" VerticalAlignment="Top" Width="300"/>
                    <WpfPlot x:Name="uxChart4" HorizontalAlignment="Left" Height="315" Margin="987,53,0,0" VerticalAlignment="Top" Width="300"/>
                    <Button Content="描画" HorizontalAlignment="Left" Margin="1212,10,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click" Height="21"/>
                </Grid>
            </TabItem>
            <TabItem Header="チャート2">
                <Grid>
                    <Button Content="描画" HorizontalAlignment="Left" Margin="1212,10,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
                    <WpfPlot x:Name="uxChart5" HorizontalAlignment="Left" Height="315" Margin="27,53,0,0" VerticalAlignment="Top" Width="300"/>
                    <WpfPlot x:Name="uxChart6" HorizontalAlignment="Left" Height="315" Margin="345,53,0,0" VerticalAlignment="Top" Width="300"/>
                    <WpfPlot x:Name="uxChart7" HorizontalAlignment="Left" Height="315" Margin="664,53,0,0" VerticalAlignment="Top" Width="300"/>
                    <WpfPlot x:Name="uxChart8" HorizontalAlignment="Left" Height="315" Margin="987,53,0,0" VerticalAlignment="Top" Width="300"/>
                </Grid>
            </TabItem>
            <TabItem Header="チャート3">
                <Grid>
                    <Button Content="描画" HorizontalAlignment="Left" Margin="1212,10,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
                    <WpfPlot x:Name="uxChart9" HorizontalAlignment="Left" Height="315" Margin="27,53,0,0" VerticalAlignment="Top" Width="300"/>
                    <WpfPlot x:Name="uxChart10" HorizontalAlignment="Left" Height="315" Margin="345,53,0,0" VerticalAlignment="Top" Width="300"/>
                    <WpfPlot x:Name="uxChart11" HorizontalAlignment="Left" Height="315" Margin="664,53,0,0" VerticalAlignment="Top" Width="300"/>
                    <WpfPlot x:Name="uxChart12" HorizontalAlignment="Left" Height="315" Margin="987,53,0,0" VerticalAlignment="Top" Width="300"/>
                </Grid>
            </TabItem>
        </TabControl>

    </Grid>
</Window>

C#のソースコード

C#側のソースコードは以下の通りです。

using ScottPlot;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ScotPlotTest
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Random rand = new Random();
            //折れ線グラフのデータ作成
            double[] xs = Enumerable.Range(0, 100).Select(i => (double)i).ToArray();
            double[] ys = Enumerable.Range(0, 100).Select(i => (double)(i + rand.Next(0,100) * ((rand.Next(1,2) == 1) ? 1 : -1))).ToArray();
            double[] ys1 = Enumerable.Range(0, 100).Select(i => Math.Sin(i * 0.1)).ToArray();
            double[] ys2 = Enumerable.Range(0, 100).Select(i => 2 + Math.Cos(i * 0.1)).ToArray();
            double[] ys3 = Enumerable.Range(0, 100).Select(i => 4 + Math.Sin(i * 0.1) * Math.Cos(i * 0.1)).ToArray();
            double[] ys4 = Enumerable.Range(0, 100).Select(i => 1000 + Math.Sin(i * 0.1) * Math.Cos(i * 0.1)).ToArray();

            //グラフの描画
            DrawLine(uxChart1,"折れ線グラフ",xs, ys);

            List<(string legend, double[] xs, double[] ys,int axis)> linedata = new List<(string legend, double[] xs, double[] ys,int axis)>();
            linedata.Add(("legend1", xs, ys1,0));
            linedata.Add(("legend2", xs, ys2,0));
            linedata.Add(("legend3", xs, ys3,0));
            linedata.Add(("legend4", xs, ys4,1));

            DrawLine(uxChart2, "折れ線グラフ(複数)", linedata);

            //散布図
            DrawScatt(uxChart3, "散布図", xs, ys);

            //円グラフ
            double[] values = { 778, 43, 283, 76, 184 };
            string[] labels = { "C#", "JAVA", "Python", "F#", "PHP" };
            DrawPie(uxChart4, "円グラフ", labels, values);

            //縦棒グラフ
            DrawColumn(uxChart5, "縦棒グラフ", labels, values);

            //横棒グラフ
            DrawBar(uxChart6, "横棒グラフ", labels, values);

            //グルーピングのデータ作成
            string[] items = { "コア数", "クロック数", "スレッド数", "キャッシュ", "価格" };
            List<(string, double[])> datas = new List<(string, double[])>();
            datas.Add(("Core-i7", new double[] { 8, 3.6, 16, 64, 70 }));
            datas.Add(("Core-i5", new double[] { 6, 2.8, 12, 32, 50 }));
            datas.Add(("Core-i3", new double[] { 4, 2.0, 8, 16, 30 }));
            datas.Add(("Pentium", new double[] { 2, 1.8, 4, 8, 10 }));
            datas.Add(("Celeron", new double[] { 2, 1.5, 4, 8, 5 }));

            //棒グラフ(グルーピング)
            DrawGroupColumn(uxChart7, "グループ", items, datas);

            //積み上げグラフ
            DrawStack(uxChart8, "積み上げ", items, datas);

            //レーダーチャート
            DrawRadar(uxChart9, "レーダー", items, datas);

            //箱ひげ図
            DrawPopulations(uxChart10, "箱ひげ", ys);

            //散布図と回帰直線
            DrawRegression(uxChart11, "回帰", xs, ys);

            ///ヒストグラム
            DrawHistgram(uxChart12, "ヒストグラム", ys,20);

        }

        /// <summary>
        /// 折れ線グラフ
        /// </summary>
        /// <param name="chart"></param>
        /// <param name="title"></param>
        /// <param name="xs"></param>
        /// <param name="ys"></param>
        private void DrawLine(WpfPlot chart, string title, double[] xs,double[] ys)
        {
            chart.Plot.Clear();
            chart.Plot.Title(title);
            chart.Plot.AddSignalXY(xs,ys);
            chart.Render();
        }

        /// <summary>
        /// 折れ線グラフ(複数)
        /// </summary>
        /// <param name="chart"></param>
        /// <param name="title"></param>
        /// <param name="datas"></param>
        private void DrawLine(WpfPlot chart, string title, List<(string legend,double[] xs, double[] ys,int axis)> datas)
        {
            chart.Plot.Clear();
            chart.Plot.Title(title);

            foreach (var data in datas)
            {
                var sig = chart.Plot.AddSignalXY(data.xs, data.ys, label: data.legend);
                sig.YAxisIndex = data.axis;
            }
            //data.axis に1つでも1以上があれば2軸を表示
            chart.Plot.YAxis2.Ticks(datas.Count(i=>i.axis > 0) > 0);
            
            chart.Plot.Legend(location: Alignment.UpperRight);
            chart.Render();
        }

        /// <summary>
        /// 散布図
        /// </summary>
        /// <param name="chart"></param>
        /// <param name="title"></param>
        /// <param name="xs"></param>
        /// <param name="ys"></param>
        private void DrawScatt(WpfPlot chart,string title, double[] xs, double[] ys)
        {
            chart.Plot.Clear();
            chart.Plot.Title(title);
            chart.Plot.AddScatter(xs, ys, lineWidth: 0);
            chart.Render();
        }

        /// <summary>
        /// 円グラフ
        /// </summary>
        /// <param name="chart"></param>
        /// <param name="title"></param>
        /// <param name="labels"></param>
        /// <param name="values"></param>
        private void DrawPie(WpfPlot chart, string title, string[] labels,double[] values)
        {
            chart.Plot.Clear();
            chart.Plot.Title(title);
            var pie = chart.Plot.AddPie(values);
            pie.SliceLabels = labels;
            pie.ShowLabels = true;
            chart.Render();
        }

        /// <summary>
        /// 縦棒グラフ
        /// </summary>
        /// <param name="chart"></param>
        /// <param name="title"></param>
        /// <param name="labels"></param>
        /// <param name="ys"></param>
        private void DrawColumn(WpfPlot chart, string title, string[] labels, double[] ys)
        {
            chart.Plot.Clear();
            chart.Plot.Title(title);
            chart.Plot.AddBar(ys,DataGen.Consecutive(ys.Length));
            chart.Plot.XTicks(labels);
            chart.Render();

        }

        /// <summary>
        /// 横棒グラフ
        /// </summary>
        /// <param name="chart"></param>
        /// <param name="title"></param>
        /// <param name="labels"></param>
        /// <param name="ys"></param>
        private void DrawBar(WpfPlot chart, string title, string[] labels, double[] ys)
        {
            chart.Plot.Clear();
            chart.Plot.Title(title);
            var bar = chart.Plot.AddBar(ys,DataGen.Consecutive(ys.Length));
            bar.Orientation = ScottPlot.Orientation.Horizontal;
            chart.Plot.YTicks(labels);
            chart.Render();

        }

        /// <summary>
        /// 箱ひげ図
        /// </summary>
        /// <param name="chart"></param>
        /// <param name="title"></param>
        /// <param name="ys"></param>
        private void DrawPopulations(WpfPlot chart, string title, double[] ys)
        {
            chart.Plot.Clear();
            chart.Plot.Title(title);
            chart.Plot.AddPopulation(new ScottPlot.Statistics.Population(ys));
            chart.Plot.XAxis.Ticks(false);
            chart.Render();
            
        }

        /// <summary>
        /// 散布図と回帰直線
        /// </summary>
        /// <param name="chart"></param>
        /// <param name="title"></param>
        /// <param name="xs"></param>
        /// <param name="ys"></param>
        private void DrawRegression(WpfPlot chart,string title, double[] xs, double[] ys)
        {

            var model = new ScottPlot.Statistics.LinearRegressionLine(xs, ys);

            chart.Plot.Clear();
            chart.Plot.Title((title != "") ? title : "Y = {model.slope:0.0000}x + {model.offset:0.0}\nR² = {model.rSquared:0.0000}");
            chart.Plot.AddScatter(xs, ys, lineWidth: 0);
            chart.Plot.AddLine(model.slope, model.offset, (xs.Min(), xs.Max()), lineWidth: 2);
            chart.Render();
        }

        /// <summary>
        /// 縦棒グラフ(グループ)
        /// </summary>
        /// <param name="chart"></param>
        /// <param name="title"></param>
        /// <param name="labels"></param>
        /// <param name="values"></param>
        private void DrawGroupColumn(WpfPlot chart, string title, string[] labels, List<(string legend,double[] ys)> values)
        {
            chart.Plot.Clear();
            chart.Plot.Title(title);

            var datas = Enumerable.Range(0, values[0].ys.Length).Select(y => Enumerable.Range(0, values.Count).Select(x => values[x].ys[y]).ToArray()).ToArray();
            chart.Plot.AddBarGroups(values.Select(i => i.legend).ToArray(), labels, datas,null);
            chart.Plot.Legend(location: Alignment.UpperRight);
            chart.Render();
        }

        /// <summary>
        /// 積み上げグラフ
        /// </summary>
        /// <param name="chart"></param>
        /// <param name="title"></param>
        /// <param name="labels"></param>
        /// <param name="values"></param>
        private void DrawStack(WpfPlot chart, string title, string[] labels, List<(string legend, double[] ys)> values)
        {
            //チャートエリアのクリア
            chart.Plot.Clear();

            //タイトルの設定
            chart.Plot.Title(title);

            //X軸のデータを生成
            var x = Enumerable.Range(0, labels.Length).Select(i => (double)i).ToArray();

            //積み上げ用配列の初期化と合計計算
            var sum = values.Select(i => i.ys.Sum()).ToArray();

            //積み上げグラフ作成(トップから順に描画)
            for(int n = 0;n < values.Count;n ++)
            {
                var bar = chart.Plot.AddBar(sum.ToArray(),x);
                bar.Label = labels[n];
                Enumerable.Range(0, sum.Length).Select(i => sum[i] = sum[i] - values[i].ys[n]).ToArray();
            }

            //凡例と軸の設定
            chart.Plot.Legend(location: Alignment.UpperRight);
            chart.Plot.XTicks(values.Select(i=>i.legend).ToArray());

            //レンダリング
            chart.Render();
        }

        /// <summary>
        /// レーダーチャート
        /// </summary>
        /// <param name="chart"></param>
        /// <param name="title"></param>
        /// <param name="labels"></param>
        /// <param name="values"></param>

        private void DrawRadar(WpfPlot chart, string title, string[] labels, List<(string legend, double[] ys)> values)
        {
            chart.Plot.Clear();
            chart.Plot.Title(title);
            double[,] plots = new double[values.Count,values[0].ys.Length];

            Enumerable.Range(0, plots.GetLength(0)).Select(i => Enumerable.Range(0, plots.GetLength(1)).Select(j => plots[i, j] = values[i].ys[j]).ToArray()).ToArray();

            var radar = chart.Plot.AddRadar(plots);
            radar.CategoryLabels = labels;
            radar.OutlineWidth = 3;
            radar.GroupLabels = values.Select(i => i.legend).ToArray();
            chart.Plot.Legend(location: Alignment.UpperRight);
            chart.Plot.Grid();
            chart.Render();
        }

        /// <summary>
        /// ヒストグラム
        /// </summary>
        /// <param name="chart"></param>
        /// <param name="title"></param>
        /// <param name="ys"></param>
        /// <param name="backet"></param>
        private void DrawHistgram(WpfPlot chart, string title, double[] ys,int backet = 10)
        {
            double max = ys.Max();
            double min = ys.Min();
            var bin = Math.Abs(max - min) / backet;

            (double[] counts, double[] binEdges) = ScottPlot.Statistics.Common.Histogram(ys,min: min, max:max, binSize: bin);
            double[] leftEdges = binEdges.Take(binEdges.Length - 1).ToArray();

            chart.Plot.Clear();
            chart.Plot.Title(title);
            var bar = chart.Plot.AddBar(values: counts,positions: leftEdges);
            bar.BarWidth = bin;
            chart.Render();
        }


        // https://scottplot.net/cookbook/4.1/

    }
}

デモプログラムに記載されているグラフ描画関数の一覧

今回のデモプログラムは再利用しやすいように関数化しています。

チャート(グラフ)名関数(メソッド)名内容
折れ線グラフDrawLine単一の折れ線グラフを描画
折れ線グラフ(複数)DrawLine複数の折れ線グラフを描画
散布図DrawScatt散布図を描画
円グラフDrawPie円グラフを描画
縦棒グラフDrawColumn縦棒グラフを描画
横棒グラフDrawBar横棒グラフを描画
棒グラフ(グルーピング)DrawGroupColumn複数の棒グラフをグルーピングして描画
積み上げグラフDrawStack積み上げグラフを描画
レーダーチャートDrawRadarレーダーチャートを描画
箱ひげ図DrawPopulations箱ひげ図とベルカーブを同時描画
散布図と回帰直線DrawRegression散布図と回帰直線を同時描画
ヒストグラムDrawHistgramヒストグラムを描画

第一引数には画面に張り付けたScottPlotコントロールを、第二引数にはグラフのタイトルを、第三引数以降に描画データ(プロットデータ)を渡すとグラフが描画されます。

例えば、コントロールに "uxChart1" という名前を付けて、xs にX方向のデータ、ysにY方向のデータが格納されていると仮定すると

//グラフの描画
DrawLine(uxChart1,"折れ線グラフ",xs, ys);

という具合です。

第三引数のプロットデータについては、大きく分けて2つの形式があります。

折れ線や棒グラフ、円グラフ、散布図は引数にプロットデータの配列を渡す仕様ですが、複数の折れ線グラフ、レーダーチャート、グルーピングした棒グラフ、積み上げグラフは複数の項目をグルーピングする形になるため、タプルをリスト形式で渡すようにしました。

詳しくはソースコードを見て頂くとして、ここでは簡単にポイントだけ説明しておきます。

単独の折れ線グラフ、散布図、散布図と回帰直線、箱ひげ図、ヒストグラムの描画関数

これらはプロットデータを配列データとして、1つまたは2つ引数に渡します。

例えば、折れ線グラフの場合は次の様になります。

DrawLine(uxChart1,"折れ線グラフ",xs, ys);

複数の折れ線グラフの描画関数

タプルのリスト形式で描画データを指定します。

タプルで、凡例タイトル(legend)、X座標の配列、y座標の配列を1まとまりにして、リストに追加していき、そのリストを引数に渡します。

List<(string legend, double[] xs, double[] ys)> linedata = new List<(string legend, double[] xs, double[] ys)>();
linedata.Add(("legend1", xs, ys1));
linedata.Add(("legend2", xs, ys2));
linedata.Add(("legend3", xs, ys3));

DrawLine(uxChart2, "折れ線グラフ(複数)", linedata);

縦棒グラフ、横棒グラフの描画関数

縦棒グラフ、横棒グラフともプロットデータとして2つ渡すのは折れ線や散布図と同じですが、横軸がdouble型配列ではなく、文字列配列になっているところが異なる点です。

//棒グラフ
 DrawBar(uxChart6, "横棒グラフ", labels, values);

円グラフの描画関数

円グラフは、ラベルと対応する値の配列を描画データとして渡します。

//円グラフのデータ
double[] values = { 778, 43, 283, 76, 184 };
string[] labels = { "C#", "JAVA", "Python", "F#", "PHP" };

//円グラフの描画
DrawPie(uxChart4, "円グラフ", labels, values);

縦棒グラフ(グルーピング)、積み上げグラフ、レーダーチャートの描画関数

これらは複数の値をグループ化して、まとめて表示するグラフであるため、タプルのリスト形式でプロットデータを設定します。

グループ化が少し分かりづらいかもしれませんが、項目名と内訳と考えてもらえれば分かりやすいかと思います。

ScottPlot をそのまま使う場合、少し面倒な値の渡し方をする必要があるので、項目名と内訳という考え方でプロットデータをセットすれば良いようにしています。

//グルーピングのデータ作成
string[] group = { "コア数", "クロック数", "スレッド数", "キャッシュ", "価格" };
List<(string, double[])> datas = new List<(string, double[])>();
datas.Add(("Core-i7", new double[] { 8, 3.6, 16, 64, 70 }));
datas.Add(("Core-i5", new double[] { 6, 2.8, 12, 32, 50 }));
datas.Add(("Core-i3", new double[] { 4, 2.0, 8, 16, 30 }));
datas.Add(("Pentium", new double[] { 2, 1.8, 4, 8, 10 }));
datas.Add(("Celeron", new double[] { 2, 1.5, 4, 8, 5 }));

//棒グラフ(グルーピング)
DrawGroupColumn(uxChart1, "グループ", group, datas);

このサンプルソース上では group という変数名を使っていますが、明細(detail) とか、内訳(breakdown) という変数名の方が良かったかもしれません。

4.0→4.1の変更点

既に旧バージョンのScottPlotを使っており、最新バージョンに置き換えようと考えている方のために、修正点を簡単に解説しておきます。

WpfPlotの plt プロパティが Plot に変わった 

ScottPlot は、WpfPlot の plt プロパティからオブジェクトを取得し、このオブジェクトに備わっている各グラフ描画メソッドを呼び出すことでグラフ描画します。

今回は、このプロパティの名前が Plot に変更されています。

//従来
var plt = uxChart.plt;
//Ver 4.1
var plt = uxChart.Plot;

グラフ描画メソッドの名前が変わった

従来のグラフ描画メソッドは、PlotBar、PlotScatter、PlotLineなど、先頭にPlotが付いていました。

Ver 4.1 からは AddBar、AddScatter、AddLine の様に先頭がAddに代わっています。

//従来
chart.plt.PlotSignalXY(data.xs, data.ys, label: data.legend);
//Ver 4.1
chart.Plot.AddSignalXY(data.xs, data.ys, label: data.legend);

グラフ描画メソッドの引数が変わった

冒頭にも説明しましたが、今までは幅や色などグラフのデザインを指定する場合は、各グラフ描画メソッドの引数を使っていました。

Ver 4.1 からは、引数で指定するのではなく、グラフ描画メソッドが返すオブジェクトに対してデザインを指定します。

この仕様変更により引数が見直されており、全てではありませんが多くのメソッドにおいて、引数の名前や引数の並び変わったり、廃止されています。

//従来(第1引数にX軸データを指定)
chart.plt.PlotBar(xs,ys);
//Ver 4.1(第2引数にX軸データを指定)
chart.Plot.AddBar(ys,xs);

Legendのロケーション指定が変わった

凡例の表示を行うLegendメソッドには、凡例をグラフのどこに表示するかを指定する location 引数があります。

Ver 4.1 では、この location 引数の指定が enum Location から enum Alignment に変更されています。

//従来
chart.plt.Legend(location: Location.upperRight);
//Ver 4.1
chart.Plot.Legend(location: Alignment.UpperRight);

これは Legend に限ったものではなく、その他のメソッドにおいても同様です。

Y第2軸が指定できるようになった

これは大変うれしい拡張機能です。

指定の方法は簡単で、グラフ描画メソッドの戻り値にあるYAxis2に、表示したい軸を設定し、最後に 2軸表示用のメソッドを呼ぶだけです。

//折線グラフ描画メソッドを呼び出し、返されるオブジェクトのYAxisIndexに軸の番号=0を指定
var sig1 = chart.Plot.AddSignalXY(~);
sig1.YAxisIndex =0;
//折線グラフ描画メソッドを呼び出し、返されるオブジェクトのYAxisIndexに軸の番号=1を指定
var sig2 = chart.Plot.AddSignalXY(~);
sig2.YAxisIndex =1;
//Y2軸を表示
chart.Plot.YAxis2.Ticks(true);

実は、X軸、Y軸とも3軸まで指定できるようになっています。

ただ、今までにX軸を3軸を使うグラフはあまり見たことが無いので、今回は取り扱いませんでしたが、XAxisIndexに使いたいX軸を指定し、XAxis3.Tick(true) とするだけです。

HistGram用のデータ集計を行うメソッドが変わった

まず名前空間の階層が次の様に変わっています。

ScottPlot.Statictics.Histogram ⇒ ScottPlot.Statistics.Common.Histogram

また、データの最大、最小、ビンサイズを指定するようになっていて、バケット数(階級をいくつに分割するか)やバーの太さなどの引数が無くなりました。

//従来
var hist = new ScottPlot.Statistics.Histogram(ys,binCount:backet);
chart.plt.PlotBar(hist.bins, hist.counts, barWidth: hist.binSize, outlineWidth: 0);
//Ver 4.1
(double[] counts, double[] binEdges) = ScottPlot.Statistics.Common.Histogram(ys,min: min, max:max, binSize: bin);
double[] leftEdges = binEdges.Take(binEdges.Length - 1).ToArray();
var bar = chart.Plot.AddBar(values: counts,positions: leftEdges);
bar.BarWidth = bin;

まとめ

今回は ScottPlot 4.1 をWPFで使う方法について、デモプログラムを交えて解説しました。

こまごまとした仕様変更が行われているため、旧バージョンから乗り換える場合はそれなりの修正が必要となります。

しかし、この記事を読んでいただければ、大枠で変更のポイントが分かるので、そんなに時間は掛からないのではないかと思います。

新しいグラフも追加されているので、それらを使いたい場合、もしくは2軸が使いたい場合は、是非ScottPlot 4.1 をご活用下さい。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次