LoginSignup
21
21

More than 5 years have passed since last update.

Math.Netを使ってヒストグラムを作る

Posted at

はじめに

ヒストグラムを作る方法を記載します。
Math.Netを使ってデータからヒストグラムを作成し、
Chartコントロールで棒グラフ表示します。

Math.Net

Math.Netは.NET開発者向け数学ライブラリです。
VisualStudioの参照設定で”Math.Net Numerics”を追加してください。

ヒストグラムの作り方

MathNet.Numerics.Statistics.Histogramクラスを使います。
コンストラクタにデータ、Bucket数、上限値、下限値を指定します。
Bucketとはヒストグラムを棒グラフにしたときの1つの棒に対応するものです。

int nBuckets = 10;
Histogram hist = new Histogram(data, nBuckets, -50 /* lower */, 50 /* upper */);

Bucket数、上限値、下限値からヒストグラムの度数をカウントする区間が決まります。
区間幅は (upper - lower) / Bucket数 となります。
例えば、upper = 50, lower = -50, Bucket数 = 10とすると、 区間幅は (50 - (-50) / 10) = 10となります。
各Bucketは (-50,-40], (-40,-30], .... , (40, 50]となります。
なお、"("は端を含まない区間記号、"]"は端を含む区間記号です。

各Bucketはindexで参照できます。indexの範囲は0~Bucket数-1です。

for (int i = 0; i < nBuckets; i++)
{
    double mid = Math.Round((hist[i].UpperBound+hist[i].LowerBound)/2, 1);
    seriesColumn.Points.Add(new DataPoint(mid, hist[i].Count));
}

例 正規乱数をヒストグラム表示する

rei.JPG

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using MathNet.Numerics.Statistics;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private Random mRand;

        public Form1()
        {
            InitializeComponent();

            // clear
            chart1.Series.Clear();
            chart1.ChartAreas.Clear();
            chart1.Titles.Clear();

            Title title1 = new Title("Histgram");

            // series
            Series seriesColumn = new Series();
            seriesColumn.LegendText = "Histgram";
            seriesColumn.ChartType = SeriesChartType.Column;

            // 正規乱数を作る
            mRand = new Random(DateTime.Now.Millisecond);
            int nData = 10000;
            double[] data = new double[nData];
            for (int i = 0; i < nData; i++)
            {
                // Box-Muller法で一様乱数から正規乱数を作る
                data[i] = boxmuller(mRand, 0 /* average */ , 10 /* sigma */);
            }

            // ヒストグラムを作る
            int nBuckets = 10;
            Histogram hist = new Histogram(data, nBuckets, -50 /* lower */, 50 /* upper */);

            for (int i = 0; i < nBuckets; i++)
            {
                double mid = Math.Round((hist[i].UpperBound+hist[i].LowerBound)/2, 1);
                seriesColumn.Points.Add(new DataPoint(mid, hist[i].Count));
            }

            // chartarea
            ChartArea area1 = new ChartArea();
            area1.AxisX.Title = "Value";
            area1.AxisY.Title = "Frequency";

            chart1.Titles.Add(title1);
            chart1.ChartAreas.Add(area1);
            chart1.Series.Add(seriesColumn);
        }

        private double boxmuller(Random rdm, double ave, double sigma)
        {
            double r1 = rdm.NextDouble();
            double r2 = rdm.NextDouble();
            double std = Math.Sqrt(-2.0 * Math.Log(r1)) * Math.Sin(2.0 * Math.PI * r2);
            return ave + std * sigma;
        }
    }
}
21
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
21