C#从CSV文件中读取字符串并绘制线图 [英] C# Read string from CSV file and plot line graph
本文介绍了C#从CSV文件中读取字符串并绘制线图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
目前,我能够从多个CSV文件中读取数据,并使用窗体应用程序绘制线图。但是,现在我需要绘制一个基于CSV文件的节名称(csv文件的第三列)的线图。
Currently, I am able to read data from multiple CSV file and plot line graph using windows form application. However, now I need to plot a line graph based on a CSV file's section name (3rd column of csv file).
修改的/新的CSV文件:名称列)
Modified/New CSV file: (Added the Section Name column)
Entropy Values,File Offset,Section Name
5.55675,1024,.text
5.3757,1536,.text
5.68973,2048,.rdata
5.6652,2560,.rdata
5.1902,3072,.data
...
- 根据节名称列,我的折线图需要在单行中,不同的部分必须以不同的颜色绘制,包括图表侧面显示的图例必须根据不同的部分名称显示。
- 1 csv file = 1 Series 。但是在csv文件中有相同的段名称(上面显示的csv文件示例,例如第一20行的.text)。 相同版面名称=相同颜色。如果我打开2个或更多的csv文件= 2系列。
- Based on the Section Name column, my line graph need to be plotted accordingly in a Single line and different sections must be plotted with different colors, including the legends shown at the side of the graph must be shown based on the different section names.
- 1 csv file = 1 Series. But there are same section names in a csv file (csv file example shown above, e.g. .text for the 1st 20lines). Same section names = same color. If I open 2 or more csv files = 2 Series. Each Series will have different colors due to different section names in the csv file.
我是一个新的编程,并会真的很感激有人可以通过我的代码进行编辑来帮助我。
I am quite new with programming, and would really appreciate someone could help me by editing from my code.
谢谢。
strong>
Read Class
public class Read
{
public string fileName { get; set; }
public string[] section { get; private set; }
public string[] header { get; private set; }
public float[,] data { get; private set; }
public int nLines { get; private set; }
public int nColumns { get; private set; }
public Read(string file)
{
string[] pieces;
fileName = Path.GetFileName(file);
string[] lines = File.ReadAllLines(file);
if (lines == null || lines.Length < 2)
{
return; // No data in file
}
header = lines[0].Split(',');
nLines = lines.Length - 1;
nColumns = header.Length;
// Read the numerical data and section name from the file
data = new float[nLines, nColumns - 1]; // 1 less than nColumns as last col is section name
section = new string[nLines];
for (int i = 0; i < nLines; i++)
{
pieces = lines[i + 1].Split(','); // Read line by line, exclude comma
if (pieces.Length != nColumns) // Check if there's 3 col in each line
{
MessageBox.Show("Invalid data at line " + (i + 2) + " of file " + fileName);
return;
}
for (int j = 0; j < nColumns - 1; j++)
{
float.TryParse(pieces[j], out data[i, j]);
}
section[i] = pieces[nColumns - 1];
}
}
}
/ strong>
Plot Class
public class Plot
{
public static void Draw(List<Read> rrList, ComboBox xBox, ComboBox yBox, Chart chart)
{
int indX = xBox.SelectedIndex;
int indY = yBox.SelectedIndex;
chart.Series.Clear();
chart.Legends.Clear();
Legend myLegend = chart.Legends.Add("myLegend");
myLegend.Title = "Legends";
Color[] colors = new Color[] { Color.Blue, Color.Red, Color.Green, Color.DarkMagenta, Color.DarkCyan, Color.Black, Color.Chocolate, Color.Purple};
var sectionColors = new Dictionary<string, int>();
int i = 0; // Series index
int iColor = -1, maxColor = -1;
foreach (Read rr in rrList)
{
float[,] data = rr.data;
int nLines = rr.nLines;
int nColumns = rr.nColumns;
string[] header = rr.header;
chart.Series.Add("Series" + i);
chart.Series[i].ChartType = SeriesChartType.Line;
chart.Series[i].IsVisibleInLegend = false;
chart.ChartAreas[0].AxisX.LabelStyle.Format = "{F0}";
chart.ChartAreas[0].AxisY.LabelStyle.Format = "{F2}";
chart.ChartAreas[0].AxisX.Title = header[indX];
chart.ChartAreas[0].AxisY.Title = header[indY];
for (int j = 0; j < nLines; j++)
{
int k = chart.Series[i].Points.AddXY(data[j, indX], data[j, indY]);
string curSection = rr.section[j];
if (sectionColors.ContainsKey(curSection))
{
iColor = sectionColors[curSection];
}
else
{
maxColor++;
iColor = maxColor; sectionColors[curSection] = iColor;
}
chart.Series[i].Points[k].Color = colors[iColor];
}
i++; // Series
} // End foreach rr
// Fill legend based on series
foreach (var x in sectionColors)
{
string section = x.Key;
iColor = x.Value;
myLegend.CustomItems.Add(colors[iColor], section); // Add new LegendItem()
}
}
}
GraphDemo类
Read rr;
List<Read> rrList = new List<Read>();
void openToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.InitialDirectory = "C:\\";
ofd.Filter = "csv files (*.csv)|*.csv|All files (*.*)|*.*";
ofd.Multiselect = true;
ofd.FilterIndex = 1;
ofd.RestoreDirectory = true;
if (ofd.ShowDialog() == DialogResult.OK)
{
try
{
rrList.Clear();
foreach (string file in ofd.FileNames)
{
rr = new Read(file);
rrList.Add(rr);
}
// Populate the ComboBoxes
if (rrList.Count > 0)
{
string[] header = rrList[0].header;
xBox.DataSource = header;
yBox.DataSource = header.Clone();
}
if (xBox.Items.Count > 1)
{
xBox.SelectedIndex = 1;
}
}
catch (Exception err)
{
MessageBox.Show(err.Message);
}
}
}
private void btnPlot_Click(object sender, EventArgs e)
{
if (rr != null)
{
Plot.Draw(rrList, xBox, yBox, chart);
}
else
{
MessageBox.Show("Error, no data to plot! Please load csv file!");
return;
}
}
推荐答案
代码:
GraphDemo(表单):
List<Read> rrList = new List<Read>();
void openToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFileDialog ff = new OpenFileDialog();
Read rr;
ff.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); //"C:\\";
ff.Filter = "csv files (*.csv)|*.csv|All files (*.*)|*.*";
ff.Multiselect = true;
ff.FilterIndex = 1;
ff.RestoreDirectory = true;
if (ff.ShowDialog() == DialogResult.OK)
{
try
{
rrList.Clear();
foreach (String file in ff.FileNames) //if ((myStream = ff.OpenFile()) != null)
{
rr = new Read(file);
rrList.Add(rr);
}
//Populate the ComboBoxes
if (rrList.Count > 0)
{
string[] header = rrList[0].header; //header of first file
xBox.DataSource = header;
yBox.DataSource = header.Clone(); //without Clone the 2 comboboxes link together!
}
if (yBox.Items.Count > 1) yBox.SelectedIndex = 1; //select second item
}
catch (Exception err)
{
//Inform the user if we can't read the file
MessageBox.Show(err.Message);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
Plot.Draw(rrList, xBox, yBox, chart);
}
class Read:
$ b
class Read:
public class Read
{
public int nLines { get; private set; }
public int nColumns { get; private set; }
public string[] header { get; private set; }
public float[,] data { get; private set; }
public string fileName { get; set; }
public string[] section { get; private set; }
public Read(string file)
{
string[] pieces;
fileName = Path.GetFileName(file);
string[] lines = File.ReadAllLines(file); // read all lines
if (lines == null || lines.Length < 2) return; //no data in file
header = lines[0].Split(','); //first line is header
nLines = lines.Length - 1; //first line is header
nColumns = header.Length;
//read the numerical data and section name from the file
data = new float[nLines, nColumns - 1]; // *** 1 less than nColumns as last col is sectionName
section = new string[nLines]; // ***
for (int i = 0; i < nLines; i++)
{
pieces = lines[i + 1].Split(','); // first line is header
if (pieces.Length != nColumns) { MessageBox.Show("Invalid data at line " + (i + 2) + " of file " + fileName); return; }
for (int j = 0; j < nColumns - 1; j++)
{
float.TryParse(pieces[j], out data[i, j]); //data[i, j] = float.Parse(pieces[j]);
}
section[i] = pieces[nColumns - 1]; //last item is section
}
}
}
$ b b
class Plot:
public class Plot
{
//public Plot() { } //no constructor required as we use a static class to be called
public static void Draw(List<Read> rrList, ComboBox xBox, ComboBox yBox, Chart chart) //***
{
int indX = xBox.SelectedIndex;
int indY = yBox.SelectedIndex;
chart.Series.Clear(); //ensure that the chart is empty
chart.Legends.Clear();
Legend myLegend = chart.Legends.Add("myLegend");
myLegend.Title = "myTitle";
//define a set of colors to be used for sections
Color[] colors = new Color[] { Color.Black, Color.Blue, Color.Red, Color.Green, Color.Magenta, Color.DarkCyan, Color.Chocolate, Color.DarkMagenta };
//use a Dictionary to keep iColor of each section
// key=sectionName, value=iColor (color index in our colors array)
var sectionColors = new Dictionary<string, int>();
int i = 0;
int iColor = -1, maxColor = -1;
foreach (Read rr in rrList)
{
float[,] data = rr.data;
int nLines = rr.nLines;
int nColumns = rr.nColumns;
string[] header = rr.header;
chart.Series.Add("Series" + i);
chart.Series[i].ChartType = SeriesChartType.Line;
//chart.Series[i].LegendText = rr.fileName;
chart.Series[i].IsVisibleInLegend = false; //hide default item from legend
chart.ChartAreas[0].AxisX.LabelStyle.Format = "{F2}";
chart.ChartAreas[0].AxisX.Title = header[indX];
chart.ChartAreas[0].AxisY.Title = header[indY];
for (int j = 0; j < nLines; j++)
{
int k = chart.Series[i].Points.AddXY(data[j, indX], data[j, indY]);
string curSection = rr.section[j];
if (sectionColors.ContainsKey(curSection))
{
iColor = sectionColors[curSection];
}
else
{
maxColor++;
iColor = maxColor; sectionColors[curSection] = iColor;
}
chart.Series[i].Points[k].Color = colors[iColor];
}
i++; //series#
} //end foreach rr
//fill custom legends based on sections/colors
foreach (var x in sectionColors)
{
string section = x.Key;
iColor = x.Value;
myLegend.CustomItems.Add(colors[iColor], section); //new LegendItem()
}
}
}
这篇关于C#从CSV文件中读取字符串并绘制线图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文