【C#】csvのデータをヒストグラム表示する

たぶんハードエンジニアの方向けです。
まとまった評価データや、検査データなどの分布を調べたいことがあると思います。
エクセルも良いのですが、ぱっとまとめて読み込んで表示できたら便利です。
今回はC#で、csvデータをヒストグラム表示させてみたいと思います。

やること
・csvデータを読み込む
・件数リストにする
・ヒストグラム表示する
・(おまけ)グラフを画像出力する

それでは順番に見ていきましょう!

目次

順番にみていく

csvデータを読み込む

実行ファイルと同じ階層にある「sample.csv」を読んで、Listの入れ子に取り込みます。
csvファイルはカンマ区切りを想定しています。
今回はデータの羅列になったものを想定しています。(xml形式などは対応していません)

string filename = "sample.csv";
List<List<double>> datas = new List<List<double>>();
System.Text.Encoding enc = System.Text.Encoding.GetEncoding("shift_jis");
string[] lines = System.IO.File.ReadAllLines(filename, enc);
foreach (string s in lines)
{
    List<double> tmp_d = new List<double>();
    List<string> tmp_str = s.Split(',').ToList();
    foreach (string ss in tmp_str)
    {
        if (ss != "")//例外処理, 空白データは無視                        
        {
            tmp_d.Add(Convert.ToDouble(ss));
        }
    }
    datas.Add(tmp_d);
}

件数リストにする

ちょっと一工夫が要ります。
まずmaxを求めます。
maxから件数リスト用のListを作ります。
MSBとLSBを決めて、先ほど読み込んだデータをLSBで丸めて比較します。
LSBの何倍にあたるか判定して、リストに加算していきます。

//max
double max = 0;
double min = 65535;
foreach (List<double> list_d in datas)
{
    foreach (double d in list_d)
    {
        if(d > max)
        {
            max = d;
        }
        if (d < min)
        {
            min = d;
        }
    }
}

double msb = max * 1.2;
double lsb = msb / 256;
var lab = new List<int>(Enumerable.Repeat(0, 256));//件数管理用のリスト

foreach (List<double> list_d in datas)
{
    foreach (double d in list_d)
    {
        double tmp_d = d / lsb;
        tmp_d = Math.Round(tmp_d, MidpointRounding.AwayFromZero);//data / lsbで丸め
        int num_lab = (int)tmp_d;
        lab[num_lab] += 1;//件数に加算
    }
}

ヒストグラム表示する

件数リストが作れれば表示するだけです。
ヒストグラムらしく見た目を整えます。

Chart chr = chart1;
chr.ChartAreas.Clear();
chr.Series.Clear();
ChartArea chartAria1 = new ChartArea("chartArea1");
chr.ChartAreas.Add(chartAria1);

chartAria1.AxisX.Minimum = 0;
chartAria1.AxisX.Maximum = msb;
chartAria1.AxisX.Interval = (msb - 0) / 8;
chartAria1.AxisY.Minimum = 0;

chartAria1.AxisX.Title = "データ";
chartAria1.AxisY.Title = "件数";

Series series = new Series();
series.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.SplineArea;
series.BorderColor = Color.Red;
series.Color = Color.FromArgb(150, Color.Red);
series.BorderWidth = 2;
series.LegendText = "データ";

int cnt = 0;
foreach (int i in lab)
{
    series.Points.AddXY(lsb * cnt, i);
    cnt += 1;
    //listBox1.Items.Add($"{i}");
}
chr.Series.Add(series);

サンプルコード

以上をまとめたのがのサンプルです。
最後におまけでヒストグラムを画像出力しています。

//csvデータをリストに取り込む
string filename = "sample.csv";
List<List<double>> datas = new List<List<double>>();
System.Text.Encoding enc = System.Text.Encoding.GetEncoding("shift_jis");
string[] lines = System.IO.File.ReadAllLines(filename, enc);
foreach (string s in lines)
{
    List<double> tmp_d = new List<double>();
    List<string> tmp_str = s.Split(',').ToList();
    foreach (string ss in tmp_str)
    {
        if (ss != "")//例外処理, 空白データは無視                        
        {
            tmp_d.Add(Convert.ToDouble(ss));
        }
    }
    datas.Add(tmp_d);
}


//ヒストグラム生成
//max
double max = 0;
double min = 65535;
foreach (List<double> list_d in datas)
{
    foreach (double d in list_d)
    {
        if(d > max)
        {
            max = d;
        }
        if (d < min)
        {
            min = d;
        }
    }
}
//MessageBox.Show($"max:{max}, min:{min}");

//表示範囲をmax*1.2にします
double msb = max * 1.2;
double lsb = msb / 256;
var lab = new List<int>(Enumerable.Repeat(0, 256));//件数管理用のリスト
//foreach (int i in lab) {listBox1.Items.Add(i); }
//MessageBox.Show($"{lab.Count}");

foreach (List<double> list_d in datas)
{
    foreach (double d in list_d)
    {
        double tmp_d = d / lsb;
        tmp_d = Math.Round(tmp_d, MidpointRounding.AwayFromZero);//data / lsb を丸め
        int num_lab = (int)tmp_d;
        lab[num_lab] += 1;//件数に加算
        //listBox1.Items.Add($"{ tmp_d}");
    }
}
//foreach(int i in lab) {listBox1.Items.Add($"{i}"); }


Chart chr = chart1;
chr.ChartAreas.Clear();
chr.Series.Clear();
ChartArea chartAria1 = new ChartArea("chartArea1");
chr.ChartAreas.Add(chartAria1);

chartAria1.AxisX.Minimum = 0;
chartAria1.AxisX.Maximum = msb;
chartAria1.AxisX.Interval = (msb - 0) / 8;
chartAria1.AxisY.Minimum = 0;

chartAria1.AxisX.Title = "データ";
chartAria1.AxisY.Title = "件数";

Series series = new Series();
series.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.SplineArea;
series.BorderColor = Color.Red;
series.Color = Color.FromArgb(150, Color.Red);
series.BorderWidth = 2;
series.LegendText = "データ";

//件数表示
int cnt = 0;
foreach (int i in lab)
{
    series.Points.AddXY(lsb * cnt, i);
    cnt += 1;
    //listBox1.Items.Add($"{i}");
}
chr.Series.Add(series);

//グラフを画像出力
string pic_chart = $"chart.png";
chr.SaveImage(pic_chart, ChartImageFormat.Png);

以上です。
誰かの助けになることができたら幸いです。

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