简体   繁体   中英

C# - Creating a Boxplot in Oxyplot

I try to get used to Oxyplot to create some charts in my C# application. So I wanted to create a Boxplot diagram with OxyPlot, but I am not able to get any results. I tried the "Getting Started" example with no problems but now I have no clue how to bind data to a BoxplotSeries . I read the documentation on GitHub for BoxPlotSeries but there are not much information listed and the examples help me neither. So can somebody can give me an example how to use BoxPlotSeries and bind data to it?

Thank you so much.

I don't know if you want to do it in WPF/XAML, if the answer is yes then you currently don't have the possibility to do it as there is no WPF wrapper for the BoxPlot Series.

I tried to port it myself, but ran into some problems, if you want to contribute please see the issue below on GitHub:

https://github.com/oxyplot/oxyplot/issues/425

EDIT: I just submitted a pull request with which you should be able to use a BoxPlot in WPF

So I found a way to create a Boxplot with OxyPlot. Just use the Class BoxPlotSeries of OxyPlot, a List object which holds the Boxplots and a little bit of math. I used CategoryAxes for x axis to distinguish the Boxplots.

So for the future, here is the Code if somebody struggles with the same problem.

 public class Item
{
    #region Public Properties

    public string Label { get; set; }

    #endregion Public Properties
}

public class BoxPlotSeriesExample
{
    #region Public Constructors

    public BoxPlotSeriesExample()
    {
    }

    #endregion Public Constructors

    #region Public Methods

    public PlotModel createBoxPlot()
    {
        const int boxes = 16;
        var plot = new PlotModel();
        var items = new Collection<Item>();

        for (int i = 1; i < boxes + 1; i++)
        {
            items.Add(new Item { Label = i.ToString() });
        }

        plot.Axes.Add(new LinearAxis
        {
            Position = AxisPosition.Left,
            MajorStep = 1,
            MinorStep = 0.25,
            TickStyle = TickStyle.Crossing,
            AbsoluteMaximum = 5.25,
            AbsoluteMinimum = -0.25
        });

        plot.Axes.Add(new CategoryAxis
        {
            Position = AxisPosition.Bottom,
            ItemsSource = items,
            LabelField = "Label",
            IsTickCentered = true,
            TickStyle = TickStyle.None,
            AbsoluteMinimum = -1,
            AbsoluteMaximum = 17,
            IsZoomEnabled = false
        });

        var lineAnnotation = new LineAnnotation
        {
            Type = LineAnnotationType.Horizontal,
            Y = 5,
            LineStyle = LineStyle.Dash,
            StrokeThickness = 2,
            Color = OxyColor.FromArgb(50, 0, 0, 0)
        };
        plot.Annotations.Add(lineAnnotation);

        lineAnnotation = new LineAnnotation
        {
            Type = LineAnnotationType.Horizontal,
            Y = 1,
            LineStyle = LineStyle.Dash,
            StrokeThickness = 1.5,
            Color = OxyColor.FromArgb(50, 0, 0, 0)
        };
        plot.Annotations.Add(lineAnnotation);

        lineAnnotation = new LineAnnotation
        {
            Type = LineAnnotationType.Horizontal,
            Y = 4,
            LineStyle = LineStyle.Solid,
            StrokeThickness = 1.5,
            Color = OxyColor.FromArgb(50, 0, 0, 0)
        };
        plot.Annotations.Add(lineAnnotation);

        lineAnnotation = new LineAnnotation
        {
            Type = LineAnnotationType.Horizontal,
            Y = 2,
            LineStyle = LineStyle.Solid,
            StrokeThickness = 1.5,
            Color = OxyColor.FromArgb(50, 0, 0, 0)
        };
        plot.Annotations.Add(lineAnnotation);

        var s1 = new BoxPlotSeries();
        s1.Fill = OxyColor.FromRgb(0x1e, 0xb4, 0xda);
        s1.StrokeThickness = 1.1;
        s1.WhiskerWidth = 1;
        var random = new Random();
        for (int i = 0; i < boxes; i++)
        {
            double x = i;
            var points = 5 + random.Next(15);
            var values = new List<double>();
            for (int j = 0; j < points; j++)
            {
                values.Add((random.NextDouble()) * 5);
            }

            values.Sort();
            var median = getMedian(values);
            int r = values.Count % 2;
            double firstQuartil = getMedian(values.Take((values.Count + r) / 2)); // 25%-Quartil
            double thirdQuartil = getMedian(values.Skip((values.Count - r) / 2)); // 75%-Quartil

            var iqr = thirdQuartil - firstQuartil; // Quartilabstand
            var step = 1.5 * iqr;
            var upperWhisker = thirdQuartil + step;
            upperWhisker = values.Where(v => v <= upperWhisker).Max();
            var lowerWhisker = firstQuartil - step;
            lowerWhisker = values.Where(v => v >= lowerWhisker).Min();
            var outliers = values.Where(v => v > upperWhisker || v < lowerWhisker).ToList();

            s1.Items.Add(new BoxPlotItem(x, lowerWhisker, firstQuartil, median, thirdQuartil, upperWhisker, outliers));
        }

        plot.Series.Add(s1);
        return plot;
    }

    #endregion Public Methods

    #region Private Methods

    private static double getMedian(IEnumerable<double> values)
    {
        var sortedInterval = new List<double>(values);
        sortedInterval.Sort();
        var count = sortedInterval.Count;
        if (count % 2 == 1)
        {
            return sortedInterval[(count - 1) / 2];
        }

        return 0.5 * sortedInterval[count / 2] + 0.5 * sortedInterval[(count / 2) - 1];
    }

    #endregion Private Methods
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM