0

プロジェクトで 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/

驚くべきことに、2 つのグラフの唯一の違いは、各グラフのデータの最初の double 値です。左の look-ok-chart の最初の double 値は 0.5685 で、別の値は 0.5686 を使用していますが、それほど大きな違いはないように聞こえます。0.0001 は右のチャートを奇妙にしました。Box シリーズの UseCustomValues プロパティを使用しようとしなかったので、使用したくありません。

2 つのデータセットの両方でグラフを正しく描画する方法を知っている人はいますか?

4

1 に答える 1

1

これは設計どおりです。ここでの解決策は、カスタム値を使用することです。ListBoxコンポーネントとTChartコンポーネントをFormにドロップし、次のコードを使用すると、違いを確認できます。

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

ここで違いを生むのは隣接ポイント 3です。最初のボックス プロットでは、innerFence3は系列の最後の値と一致しますが、2 番目のボックス プロットではわずかに小さくなっています。したがって、このコード:

for (i = med; i < N; i++) if (SampleValues[i] > innerFence3) break;
adjacentPoint3 = SampleValues[i - 1];

最初のシリーズよりも 1 ステップ前に中断し、最後ではなく最後から 2 番目の値が使用されています。したがって、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;
于 2013-07-22T10:22:41.353 に答える