我在一个项目中使用Teechart(.Net 2009),当我绘制一个具有特定双点的方框时,我发现了一些奇怪的事情。
这是我重现问题的xaml代码。
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<WindowsFormsHost x:Name="chartHost"/>
<WindowsFormsHost x:Name="chartHost2" Grid.Column="1"/>
</Grid>
</Window>
这是上述xaml文件的后面代码。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
SetChart(new[] { 0.5685, 0.7141, 0.7301, 0.748, 0.7847, 1.2127 }, chartHost);
SetChart(new[] { 0.5686, 0.7141, 0.7301, 0.748, 0.7847, 1.2127 }, chartHost2);
}
private void SetChart(double[] values, WindowsFormsHost host)
{
var chart = new TChart();
var box = new Box(chart.Chart);
box.Add(values);
box.ExtrOut.HorizSize = 0;
box.ExtrOut.VertSize = 0;
box.MildOut.HorizSize = 0;
box.MildOut.VertSize = 0;
chart.Axes.Left.Maximum = 1.2;
chart.Axes.Left.Minimum = 0.5;
host.Child = chart;
}
}
结果如下所示。 (请单击链接查看捕获的图像。由于信誉限制,我目前无法附加图像。)
http://www.flickr.com/photos/99238307@N06/9341426974/
令人惊讶的是,两个图表之间的唯一区别是每个图表数据的第一个双精度值。左边看起来好的图表的第一个双重值是0.5685而另一个使用0.5686,听起来并没有那么大的区别。 0.0001使得正确的图表变得奇怪。我没有尝试使用Box系列的UseCustomValues属性,我不想使用它。
有人知道如何使用两个数据集正确绘制图表吗?
答案 0 :(得分:1)
这是按照设计的。这里的解决方案是使用自定义值。您可以通过在表单中删除 ListBox 和 TChart 组件并使用以下代码来查看差异:
public Form1()
{
InitializeComponent();
InitializeChart();
}
private void InitializeChart()
{
bool automatic = true;
SetChart(new[] { 0.5685, 0.7141, 0.7301, 0.748, 0.7847, 1.2127 }, automatic);
SetChart(new[] { 0.5686, 0.7141, 0.7301, 0.748, 0.7847, 1.2127 }, automatic);
tChart1.Axes.Left.SetMinMax(0.55, 1.25);
}
private void SetChart(double[] values, bool auto)
{
var box = new Steema.TeeChart.Styles.Box(tChart1.Chart);
box.Add(tChart1.Series.Count, values);
if (auto)
{
box.ReconstructFromData();
listBox1.Items.Add("Series: " + box.Title.ToString());
listBox1.Items.Add("Median: " + box.Median.ToString());
listBox1.Items.Add("Quartile1: " + box.Quartile1.ToString());
listBox1.Items.Add("Quartile3: " + box.Quartile3.ToString());
listBox1.Items.Add("InnerFence1: " + box.InnerFence1.ToString());
listBox1.Items.Add("InnerFence3: " + box.InnerFence3.ToString());
listBox1.Items.Add("OuterFence1: " + box.OuterFence1.ToString());
listBox1.Items.Add("OuterFence3: " + box.OuterFence3.ToString());
listBox1.Items.Add("AdjacentPoint1: " + box.AdjacentPoint1.ToString());
listBox1.Items.Add("AdjacentPoint3: " + box.AdjacentPoint3.ToString());
listBox1.Items.Add("-------------------------");
}
else
{
box.UseCustomValues = !auto;
box.Median = 0.73905;
box.OuterFence1 = 0.0357;
box.OuterFence3 = 1.5337;
box.InnerFence1 = 0.3567;
box.InnerFence3 = 1.2127;
box.Quartile1 = 0.6777;
box.Quartile3 = 0.8917;
box.AdjacentPoint1 = box.YValues[0];
box.AdjacentPoint3 = 1.2127;
box.Median = 0.73905;
}
}
自动变量 true ,您将看到自动计算的值,如下图所示:
将其设置为 false 它将使用手动自定义值。要了解差异,您应该了解如何实现 ReconstructFromData()方法(您可以使用反射器工具进行检查):
/// <summary>
/// Reconstructs the box plot from series data
/// </summary>
public void ReconstructFromData()
{
int N = SampleValues.Count;
if (N > 0)
{
double InvN = 1.0 / N;
/* calculate median */
int med = N / 2;
if ((N % 2) == 0) median = 0.5 * (SampleValues[med - 1] + SampleValues[med]);
else median = SampleValues[med];
/* calculate Q1 && Q3 */
quartile1 = N > 1 ? Percentile(SampleValues, 0.25) : SampleValues[0];
quartile3 = N > 1 ? Percentile(SampleValues, 0.75) : SampleValues[0];
/* calculate IQR */
double iqr = quartile3 - quartile1;
innerFence1 = quartile1 - whiskerLength * iqr;
innerFence3 = quartile3 + whiskerLength * iqr;
/* find adjacent points */
int i;
for (i = 0; i <= med; i++) if (SampleValues[i] > innerFence1) break;
adjacentPoint1 = SampleValues[i];
for (i = med; i < N; i++) if (SampleValues[i] > innerFence3) break;
adjacentPoint3 = SampleValues[i - 1];
/* calculate outer fences */
outerFence1 = quartile1 - 2 * whiskerLength * iqr;
outerFence3 = quartile3 + 2 * whiskerLength * iqr;
}
}
这里有什么区别是 adjacentPoint3 。在第一个框图中, innerFence3 与系列中的最后一个值重合,而在第二个框图中,它稍微小一些。因此,这段代码:
for (i = med; i < N; i++) if (SampleValues[i] > innerFence3) break;
adjacentPoint3 = SampleValues[i - 1];
比第一个系列中断前一步,使用倒数第二个值而不是最后一个。因此, AdjacentPoint3 和正在绘制的内容之间存在差异。
要自动计算数据,您可以执行以下操作:
box.ReconstructFromData();
box.UseCustomValues = true;
box.Median = box.Median;
box.OuterFence1 = box.OuterFence1;
box.OuterFence3 = box.OuterFence3;
box.InnerFence1 = box.InnerFence1;
box.InnerFence3 = box.InnerFence3;
box.Quartile1 = box.Quartile1;
box.Quartile3 = box.Quartile3;
box.AdjacentPoint1 = box.AdjacentPoint1;
box.AdjacentPoint3 = box.YValues[box.Count-1];
box.Median = box.Median;