2013-07-22 145 views
0

我在一个项目中使用的TeeChart(2009 .NET),我发现了一些奇怪的事情发生时,我得出具体双倍积分的盒子。奇怪的箱形图形状的TeeChart

这是我的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/[email protected]/9341426974/

出人意料的是,两幅图之间的唯一区别是,每个图表的数据的第一双值。左边看起来好的图的第一个双倍值是0.5685,而另一个值是0.5686,这听起来没有那么大的差别。 0.0001使得正确的图表变得怪异。我没有尝试使用Box系列的UseCustomValues属性,我不想使用它。

任何人知道如何与这两个两个数据设置正确绘制图表?

回答

1

这是有意设计的。这里的解决方案是使用自定义值。

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; 
    } 
} 

随着自动变量为真正你会看到自动计算出的值,如下所示:您可以通过删除列表框表格 TChart组件和使用此代码看到了差距这一形象:

enter image description here

将其设置为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; 
+0

感谢您的答复。我试图使用_ReconstructFromData_方法,但它不起作用。 box.ReconstructFromData(); 我在SetChart方法结束时加入此行。结果是一样的。 :-( –

+0

@BruceYang在进一步调查问题后,我们发现这不是一个错误,我更正了上面的答案 –

+0

感谢您的详细信息,它运作良好! –