Данные графика со стандартными диапазонами отклонения в C#

Примеры Нарисуйте нормальную кривую распределения в C# и Нарисуйте масштабированное нормальное распределение на C# , покажите один подход для визуализации распределения данных. В этом примере показан метод, который позволяет визуализировать, где конкретное значение данных находится в последовательности наборов данных.

В этом примере используется другой набор данных для каждого из возрастов с 6 по 13. (Вы можете использовать другие виды данных, такие как продажи в течение нескольких лет, дорожные сбои в течение нескольких лет, количество тестов по сравнению с часами обучения и т. д. .) Черная линия, проходящая через график, показывает средства для разных наборов данных. Цветные полосы показывают 0,5, 1,5 и 2,5 стандартных отклонения от средств.

Следующий код показывает, как пример инициализирует свои данные.

// Средние и стандартные данные отклонения.
private const int MinAge = 6;
private float[] Means =
    { 62, 56, 43, 42, 39, 36, 32, 31, };
private float[] StdDevs =
    { 15, 9, 8, 8, 7, 5, 5, 6, };

// Некоторые контрольные точки.
private PointF[] TestPoints =
{
    new PointF(6, 58),
    new PointF(7, 63),
    new PointF(9, 55),
    new PointF(11, 39),
    new PointF(13, 29),
};

Этот код просто создает массивы для хранения средних и стандартных отклонений для каждого возраста. Затем он создает массив тестовых точек для построения графика на графике.

Метод DrawGraph примера рисует график. Это довольно долго, так что это показано здесь по частям. Вот первая часть:

// Рисуем график.
private void DrawGraph(int min_age, float[] means, float[] stddevs)
{
    int max_age = min_age + means.Length - 1;

    // Получаем минимальное и максимальное значения.
    const float max_dev = 2.5f;
    float min_value = means[0] - max_dev * stddevs[0];
    float max_value = means[0] + max_dev * stddevs[0];
    for (int i = 0; i < means.Length; i++)
    {
        if (min_value > means[i] - max_dev * stddevs[i])
            min_value = means[i] - max_dev * stddevs[i];
        if (max_value < means[i] + max_dev * stddevs[i])
            max_value = means[i] + max_dev * stddevs[i];
    }
    if (min_value > 0) min_value = 0;

    float hgt = 1.2f * (max_value - min_value);
    float middle = (max_value + min_value) / 2f;
    min_value = middle - hgt / 2f;
    max_value = middle + hgt / 2f;

    // Сделайте преобразование для рисования.
    RectangleF world = new RectangleF(
        min_age - 1f, min_value,
        max_age - min_age + 1.5f, max_value - min_value);
    PointF[] device_points =
    {
        new PointF(0, picGraph.ClientSize.Height),
        new PointF(
            picGraph.ClientSize.Width,
            picGraph.ClientSize.Height),
        new PointF(0, 0),
    };
    Matrix transform = new Matrix(world, device_points);

Этот код вычисляет минимальные и максимальные значения, которые программа должна отображать. Для этого он проходит через средства и добавляет и вычитает в 2,5 раза стандартное отклонение для каждого.

После нахождения самых больших и наименьших значений, код создает RectangleF, представляющий мировые координаты, которые он будет строить. (Минимальные и максимальные координаты X и Y необходимо будет рисовать.) Он создает массив PointF, чтобы определить, где должны быть отображены верхние левые, верхние правые и нижние левые углы координат мира чтобы правильно отображаться на PictureBox. Затем он использует RectangleF и массив PointF для создания преобразования для выполнения этого сопоставления.

Следующий фрагмент кода рисует базовый граф.

    Bitmap bm = new Bitmap(
        picGraph.ClientSize.Width,
        picGraph.ClientSize.Height);
    using (Graphics gr = Graphics.FromImage(bm))
    {
        using (Pen pen = new Pen(Color.Red, 0))
        {
            gr.SmoothingMode = SmoothingMode.AntiAlias;
            gr.Transform = transform;

            // Нарисуем конверты стандартного отклонения.
            using (SolidBrush brush =
                new SolidBrush(Color.FromArgb(255, 128, 128)))
            {
                pen.Color = brush.Color;
                DrawEnvelope(gr, min_age, means, stddevs,
                    2.5f, brush, pen);
            }
            using (SolidBrush brush =
                new SolidBrush(Color.FromArgb(255, 255, 128)))
            {
                pen.Color = brush.Color;
                DrawEnvelope(gr, min_age, means, stddevs,
                    1.5f, brush, pen);
            }
            using (SolidBrush brush =
                new SolidBrush(Color.FromArgb(128, 255, 128)))
            {
                pen.Color = brush.Color;
                DrawEnvelope(gr, min_age, means, stddevs,
                    0.5f, brush, pen);
            }

            // Рисуем кривую.
            List points = new List();
            for (int i = 0; i < means.Length; i++)
                points.Add(new PointF(i + min_age, means[i]));
            pen.Color = Color.Black;
            gr.DrawLines(pen, points.ToArray());

Этот код создает Bitmap для соответствия PictureBox, а затем создает связанный объект Graphics.

Затем он создает Pen с толщиной 0. Когда вы рисуете с помощью Pen с толщиной 0, библиотека рисования GDI + рисует ширину линии 1, даже если линии линии трансформируются. Если вы используете линию с другой толщиной, преобразование также относится к ширине линии, поэтому вы получаете искаженные линии. В этом примере весь график покрывается линиями. (Установите толщину на 1 и убедитесь сами.)

Код устанавливает свойство Graphics объекта SmoothingMode для создания плавных линий. Затем он устанавливает свойство Transform, чтобы строки отображались из мировых координат в систему координат Bitmap.

Далее код создает серию кистей и передает их и соответствующим образом окрашивает Pen в метод DrawEnvelope, чтобы нарисовать полосы, показывающие кратные стандартным отклонениям. (Этот метод описан ниже).

Этот фрагмент кода завершен путем рисования кривой, соединяющей средства.

Следующий фрагмент кода рисует ось X.

            // Рисуем и маркируем оси.
            pen.Color = Color.Black;
            using (Font font = new Font("Arial", 8))
            {
                gr.TextRenderingHint =
                    TextRenderingHint.AntiAliasGridFit;
                using (StringFormat sf = new StringFormat())
                {
                    sf.Alignment = StringAlignment.Center;
                    sf.LineAlignment = StringAlignment.Near;

                    // Нарисуем ось X.
                    // Нарисуем ось.
                    gr.DrawLine(pen, min_age, 0, max_age, 0);

                    // Нарисуем метки.
                    for (int x = min_age; x <= max_age; x++)
                        gr.DrawLine(pen, x, 0, x, max_value);

                    // Пометьте возраст.
                    List tick_points = new List();
                    List tick_labels = new List();
                    PointF[] label_points_array;
                    for (int x = min_age; x <= max_age; x++)
                    {
                        tick_points.Add(new PointF(x, 0));
                        tick_labels.Add(x.ToString());
                    }
                    label_points_array = tick_points.ToArray();
                    transform.TransformPoints(label_points_array);
                    gr.Transform = new Matrix();
                    for (int i = 0; i <
                        label_points_array.Length; i++)
                    {
                        gr.DrawString(tick_labels[i], font,
                            Brushes.Black, label_points_array[i],
                            sf);
                    }

Этот код создает объекты Font и StringFormat для использования при рисовании текста. Затем он рисует линию оси X и отметки.

Чтобы пометить метки, код создает два списка, один из которых содержит место размещения каждой метки и текст ярлыка. Он преобразует список точек в массив и использует метод transform объекта transform для сопоставления точек из мировых координат с системой координат Bitmap.

Далее код сбрасывает свойство Transform объекта Graphics объекта в новую Matrix, которая представляет преобразование идентичности. Это не позволяет преобразованию применить текст ярлыка и исказить символы.

Код заканчивается путем циклического перехода по меткам, рисуя каждую метку в ее преобразованном местоположении.

Код, который рисует ось Y, подобен, поэтому он не показан здесь.

Следующий код показывает последнюю часть метода DrawGraph.

                } // StringFormat
            } // Шрифт

            // Тестовые точки.
            transform.TransformPoints(TestPoints);
            gr.Transform = new Matrix();
            foreach (PointF point in TestPoints)
            {
                gr.FillRectangle(Brushes.Red,
                    point.X - 3, point.Y - 3, 6, 6);
            }
        } // Ручка
    } // Графика

    picGraph.Image = bm;
}

Этот код просто разбивает точки тестовых данных.

В следующем коде показан метод DrawEnvelope, который рисует одну из затененных областей на графике.

// Нарисуем конверт для dev_mult раз стандартные отклонения.
private void DrawEnvelope(Graphics gr, int min_age,
    float[] means, float[] stddevs,
    float dev_mult, Brush brush, Pen pen)
{
    List points = new List();
    for (int i = 0; i < means.Length; i++)
        points.Add(new PointF(
            i + min_age,
            means[i] + dev_mult * stddevs[i]));
    for (int i = means.Length - 1; i >= 0; i--)
        points.Add(new PointF(
            i + min_age,
            means[i] - dev_mult * stddevs[i]));

    gr.FillPolygon(brush, points.ToArray());
    gr.DrawPolygon(pen, points.ToArray());
}

Этот метод создает список объектов PointF. Затем он перебирает точки добавления данных в список. Сначала он идет слева направо, добавляя средние значения плюс кратное их стандартным отклонениям, чтобы получить координаты Y вдоль вершины области, которую он рисует. Затем метод идет слева направо, вычитая кратное их стандартным отклонениям от средних значений, чтобы получить координаты Y вдоль нижней части области.

После того, как он сгенерировал точки, представляющие область, код заполнит ее, а затем очерчивает ее с помощью Brush и Pen, переданных в качестве параметров. (В этом примере Brush и Pen имеют один и тот же цвет, поэтому вы не видите эффект Pen. Я изначально планировал чтобы очертить каждую область немного темным цветом, но решили, что эта версия выглядит лучше.)

Источник: http://csharphelper.com/blog/2015/09/plot-data-with-standard-deviation-ranges-in-c/

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Adblock
detector