我正在使用.Net 4.0 中的图表库来创建包含多个系列的堆叠柱形图。我的目标是一个直方图,显示多个系列(教师)每天的累积操作数(报告完成情况)。经常缺少数据(特定老师当天没有活动)。
当系列中缺少数据时,条形图中会出现间隙:
我的代码:
public ActionResult CompletionHistogram(int sid, int width, int height)
{
Site site = SiteRepository.Get(sid);
if (site == null)
return new HttpNotFoundResult();
Chart chart = new Chart();
chart.Height = height;
chart.Width = width;
ChartArea area = chart.ChartAreas.Add("Default");
// Treat each teacher as a series
foreach (Teacher t in site.Teachers)
{
Series series = chart.Series.Add(t.FullName);
series.ChartType = SeriesChartType.StackedColumn;
series.Name = t.FullName;
// Group completions by day (filter out incomplete reports and null timestamps)
var groups = t.StudentReports
.Where<StudentReport>(rep => rep.IsComplete && rep.FirstSaveTimestamp.HasValue)
.GroupBy<StudentReport, DateTime>(rep => rep.FirstSaveTimestamp.Value.Date);
bool hasPoints = false;
foreach (var g in groups)
{
series.Points.AddXY(g.Key, g.Count());
hasPoints = true;
}
series.IsValueShownAsLabel = true;
series.ToolTip = "#VALX";
if (hasPoints)
chart.DataManipulator.InsertEmptyPoints(1, IntervalType.Days, series);
}
area.AxisX.LabelStyle.Format = "ddd M/d";
return new ChartResult(chart);
}
如何删除
我有办法做到这一点。
很抱歉回答很长,但我发现您尝试实现此答案的方式会影响它是否有效。
添加点时需要手动将点设置为零。 注意:我无法通过事后添加零点来完成这项工作。
请参阅下面的示例和生成的屏幕截图:
chart1.Series.Clear();
chart1.Series.Add(new Series());
chart1.Series.Add(new Series());
chart1.Series.Add(new Series());
chart1.Series.Add(new Series());
foreach (Series s in chart1.Series)
{
s.ChartType = SeriesChartType.StackedColumn;
}
//chart1.Series[0].Points.Add(new DataPoint(0, 0));
chart1.Series[0].Points.Add(new DataPoint(1, 3));
chart1.Series[0].Points.Add(new DataPoint(2, 3));
chart1.Series[0].Points.Add(new DataPoint(3, 3));
chart1.Series[1].Points.Add(new DataPoint(0, 3));
//chart1.Series[1].Points.Add(new DataPoint(1, 0));
chart1.Series[1].Points.Add(new DataPoint(2, 3));
chart1.Series[1].Points.Add(new DataPoint(3, 3));
chart1.Series[2].Points.Add(new DataPoint(0, 3));
chart1.Series[2].Points.Add(new DataPoint(1, 3));
//chart1.Series[2].Points.Add(new DataPoint(2, 0));
chart1.Series[2].Points.Add(new DataPoint(3, 3));
chart1.Series[3].Points.Add(new DataPoint(0, 3));
chart1.Series[3].Points.Add(new DataPoint(1, 3));
chart1.Series[3].Points.Add(new DataPoint(2, 3));
//chart1.Series[3].Points.Add(new DataPoint(3, 0));
chart1.SaveImage("C:\\Before.png", ChartImageFormat.Png);
“before.png”图片:
现在删除给定 x 值处没有数据点的系列的注释:
(注意!我发现如果您在给定的 x 值处添加点(在最后使 y = 0 的值),即在我保存图像之前,它不起作用。系列中点的顺序似乎是对于 StackedColumn 来说很重要,除了研究如何回答这个问题之外,我从未使用过这种类型,因此这可能是此类用户的常识)
chart1.Series.Clear();
chart1.Series.Add(new Series());
chart1.Series.Add(new Series());
chart1.Series.Add(new Series());
chart1.Series.Add(new Series());
foreach (Series s in chart1.Series)
{
s.ChartType = SeriesChartType.StackedColumn;
}
chart1.Series[0].Points.Add(new DataPoint(0, 0));
chart1.Series[0].Points.Add(new DataPoint(1, 3));
chart1.Series[0].Points.Add(new DataPoint(2, 3));
chart1.Series[0].Points.Add(new DataPoint(3, 3));
chart1.Series[1].Points.Add(new DataPoint(0, 3));
chart1.Series[1].Points.Add(new DataPoint(1, 0));
chart1.Series[1].Points.Add(new DataPoint(2, 3));
chart1.Series[1].Points.Add(new DataPoint(3, 3));
chart1.Series[2].Points.Add(new DataPoint(0, 3));
chart1.Series[2].Points.Add(new DataPoint(1, 3));
chart1.Series[2].Points.Add(new DataPoint(2, 0));
chart1.Series[2].Points.Add(new DataPoint(3, 3));
chart1.Series[3].Points.Add(new DataPoint(0, 3));
chart1.Series[3].Points.Add(new DataPoint(1, 3));
chart1.Series[3].Points.Add(new DataPoint(2, 3));
chart1.Series[3].Points.Add(new DataPoint(3, 0));
// If you add the empty points here, it does not seem to work.
// Empty points are as follows, and are already added above in the 'after' example.
// chart1.Series[0].Points.Add(new DataPoint(0, 0));
// chart1.Series[1].Points.Add(new DataPoint(1, 0));
// chart1.Series[2].Points.Add(new DataPoint(2, 0));
// chart1.Series[3].Points.Add(new DataPoint(3, 0));
chart1.SaveImage("C:\\After.png", ChartImageFormat.Png);
“after.png”图片:
因此,鉴于您无法在事后添加零点(尽管您可能可以插入它们?),您将需要将代码修改为如下所示:
var allPossibleGroups = t.StudentReports;
var groups = t.StudentReports
.Where<StudentReport>(rep => rep.IsComplete && rep.FirstSaveTimestamp.HasValue)
.GroupBy<StudentReport, DateTime>(rep => rep.FirstSaveTimestamp.Value.Date);
bool hasPoints = false;
foreach (var g in allPossibleGroups)
{
if(groups.ContainsKey(g))
{
series.Points.AddXY(g.Key, g.Count());
hasPoints = true;
}
else
{
series.Points.AddXY(g.Key, 0);
}
}
很抱歉代码块很长,但是这个示例是必要的,以演示如何使其工作,而不是陷入在末尾添加空点(其中 y = 0)的陷阱,因为这是行不通的。
如果您需要更多帮助,请告诉我。
我自己也遇到了同样的问题,想分享正确的解决方案:
使用 DataManipulator 插入缺失的 (x,y) 值:
foreach (Series s in chart.Series)
{
chart.DataManipulator.Sort(PointSortOrder.Ascending, "X", s);
chart.DataManipulator.InsertEmptyPoints(1, IntervalType.Number, s);
}
由于某种原因,循环遍历系列对我不起作用,但下一个解决方案就像魅力一样:
Chart1.DataManipulator.InsertEmptyPoints(1, IntervalType.Number, "Series1, Series2, Series3, Series4")