たぶんハードエンジニアの方向けです。
まとまった評価データや、検査データなどの分布を調べたいことがあると思います。
エクセルも良いのですが、ぱっとまとめて読み込んで表示できたら便利です。
今回は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);
以上です。
誰かの助けになることができたら幸いです。