Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.89/18: Рейтинг темы: голосов - 18, средняя оценка - 4.89
1 / 1 / 0
Регистрация: 22.12.2014
Сообщений: 42
1

Гистограмма частот

30.07.2019, 06:52. Показов 3351. Ответов 18
Метки нет (Все метки)

Добрый день.
Захотелось мне реализовать нормальное распределение. Гугли-гуглил, нагуглил преобразование Бокса — Мюллера, нагуглил реализацию, она какие-то числа выдаёт. Но вдруг она выдает что-то не то? Надо ведь проверить, а для этого надо построить график. Погуглил, пишут для графиков юзай Windows Forms -> Charts. Окей, поковырял Charts, но он, судя по всему, не умеет строить гистограммы частоты вхождения как Excel, а значит мне надо как-то в программе эти частоты самому посчитать.

И дальше я вижу два пути, оба мне не нравятся:
1) В массиве чисел нахожу минимальное и максимальное, исходя из них бью множество чисел на интервалы, дальше каждое число в массиве проверяю на принадлежность каждому из интервалов. Получается большое количество операций сравнения.
2) Вспоминаю университетский матан и копаю в сторону преобразований фурье. Предварительный поиск показывает, что люди это применяют в основном для обработки разных сигналов, а не для отрисовки массивов чисел.

Из всего этого вытекает вопрос - где я свернул не туда? Как с наименьшим сопротивлением реализовать график частоты вхождения вещественных чисел в массив?
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
30.07.2019, 06:52
Ответы с готовыми решениями:

Гистограмма в Excel
Здравствуйте, хочу построить гистограмму на основе данных по продажам. Есть следующий код: using...

Задача Гистограмма
Скачайте проект Names и изучите его. В классе HistogramTask напишите код подготовки данных для...

Гистограмма и прямые в ZedGraph
Добрый вечер!!! Подскажите пожалуйста как вывести линию поверх Гистограммы. После этого кода в...

Гистограмма по чб изображению, медианный фильтр
Уважаемые форумчане! Очень нуждаюсь в вашей помощи... Есть программа, которая загружает/сохраняет...

18
Модератор
Эксперт .NET
10893 / 7733 / 2095
Регистрация: 21.04.2018
Сообщений: 23,266
Записей в блоге: 2
30.07.2019, 16:02 2
Цитата Сообщение от Dr2 Посмотреть сообщение
Из всего этого вытекает вопрос - где я свернул не туда? Как с наименьшим сопротивлением реализовать график частоты вхождения вещественных чисел в массив?
Верный первый способ.
При любой обработке нужно обработать каждое число. Целочисленные операции сравнения, сложения относятся к самым быстрым. Так что ни чего быстрее всё равно не получится.
1
1 / 1 / 0
Регистрация: 22.12.2014
Сообщений: 42
31.07.2019, 01:00  [ТС] 3
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Верный первый способ.
При любой обработке нужно обработать каждое число. Целочисленные операции сравнения, сложения относятся к самым быстрым. Так что ни чего быстрее всё равно не получится.
Меня смущает количество проверок при поиске принадлежности интервалам. Например если бить на 128 интервалов и начинать поиск из середины, то это минимум 7*2 проверок для каждого числа из массива.
0
3137 / 2228 / 1100
Регистрация: 14.08.2016
Сообщений: 7,617
31.07.2019, 01:13 4
сортировку массива не предлагать?
1
1 / 1 / 0
Регистрация: 22.12.2014
Сообщений: 42
31.07.2019, 01:15  [ТС] 5
Цитата Сообщение от Diamante Посмотреть сообщение
сортировку массива не предлагать?
Чем мне поможет сортировка?
0
3137 / 2228 / 1100
Регистрация: 14.08.2016
Сообщений: 7,617
31.07.2019, 01:17 6
в сортирнутом массиве уже и сравнивать то особо нечего, нету необходимости искать в диапазонах, куда же попадет значение...
0
1 / 1 / 0
Регистрация: 22.12.2014
Сообщений: 42
31.07.2019, 01:21  [ТС] 7
Цитата Сообщение от Diamante Посмотреть сообщение
в сортирнутом массиве уже и сравнивать то особо нечего, нету необходимости искать в диапазонах, куда же попадет значение...
Проверяем входит ли число в первый интервал, дальше перебираем числа, пока не находим то, которое не входит и начинаем перебирать интервалы. Да, это имеет смысл, спасибо.
0
Модератор
Эксперт .NET
10893 / 7733 / 2095
Регистрация: 21.04.2018
Сообщений: 23,266
Записей в блоге: 2
31.07.2019, 01:54 8
Лучший ответ Сообщение было отмечено Dr2 как решение

Решение

Цитата Сообщение от Dr2 Посмотреть сообщение
Меня смущает количество проверок при поиске принадлежности интервалам. Например если бить на 128 интервалов и начинать поиск из середины, то это минимум 7*2 проверок для каждого числа из массива.
Очень легко решается через LINQ группировку, но по скорости сортировка, наверное, будет быстрее

Допустим (пишу здесь - возможны мелкие ошибки):
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int countRange = 10; // Количество диапазонов 
double min = -1000;
double max = + 500;
double rangeSize = (max-min) /countRange; // Размер диапазона
 
// Рандомный массив
Random rand = new Random();
List<double> list = Enumerable.Range(1,1_000_000).Select(x => rand.NextDouble()*(max-min)+min).ToList();
 
// Массив распределения по диапазонам - получение через группировку
List<int> groupFreq = list.GroupBy(x => (int) (x/rangeSize)).Select(x => x.Count).ToList();
 
// Массив распределения по диапазонам - получение через сортировку
List<int> sortFreq =  new List<int> () {0};
double boundary = min;
list.Sort();
foreach (double x in list)
{
      if ((x - boundary ) > rangeSize)
      {
           boundary += rangeSize;
           sortFreq.Insert(0 ,1); 
       }
       else
           sortFreq[0]++;
}
1
1 / 1 / 0
Регистрация: 22.12.2014
Сообщений: 42
31.07.2019, 08:17  [ТС] 9
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Очень легко решается через LINQ группировку, но по скорости сортировка, наверное, будет быстрее
Я не использовал LINQ и у меня с трудом укладываются в голове лямбда-выражения, поэтому хочу уточнить, правильно ли я все понял:

C#
1
2
3
// Рандомный массив
Random rand = new Random();
List<double> list = Enumerable.Range(1,1_000_000).Select(x => rand.NextDouble()*(max-min)+min).ToList();
Создаем последовательность целых чисел от 1 до 1000000
C#
1
.Range(1,1_000_000)
Каждое число в этой последовательности передаем на вход Select, а он возвращает нам просто случайное число*1500-1000. Т.е. просто генерируем миллион случайных чисел.
C#
1
.Select(x => rand.NextDouble()*(max-min)+min)

C#
1
2
// Массив распределения по диапазонам - получение через группировку
List<int> groupFreq = list.GroupBy(x => (int) (x/rangeSize)).Select(x => x.Count).ToList();
Мы передаем наш миллион случайных чисел в GroupBy и для каждого из них создаём целочисленный ключ, который так же является номером интервала, в который это число входит. GroupBy возвращает объект/список объектов (какого типа? как это выглядит?), в котором для каждого из ключей будут храниться все числа вошедшие в соответствующие интервал.
C#
1
.GroupBy(x => (int) (x/rangeSize))
Для каждого из этих объектов Select считает длину (то есть все значения, хранимые внутри ключа?) и возвращает её, это и будет частота вхождения числа в интервал.
C#
1
.Select(x => x.Count)
0
Модератор
Эксперт .NET
10893 / 7733 / 2095
Регистрация: 21.04.2018
Сообщений: 23,266
Записей в блоге: 2
31.07.2019, 08:56 10
Цитата Сообщение от Dr2 Посмотреть сообщение
Я не использовал LINQ и у меня с трудом укладываются в голове лямбда-выражения, поэтому хочу уточнить, правильно ли я все понял:
Цитата Сообщение от Dr2 Посмотреть сообщение
Создаем последовательность целых чисел от 1 до 1000000
Каждое число в этой последовательности передаем на вход Select, а он возвращает нам просто случайное число*1500-1000. Т.е. просто генерируем миллион случайных чисел.
Да, это последовательность в миллион элементов int начиная с 1. Потом Select преобразует её в double со случайными значениями (равномерное распределение) от значения min (включительно) до значения max(исключительно). Это тестовая последовательность. Вместо неё у вас потом будут свои данные.

Цитата Сообщение от Dr2 Посмотреть сообщение
Мы передаем наш миллион случайных чисел в GroupBy и для каждого из них создаём целочисленный ключ, который так же является номером интервала, в который это число входит. GroupBy возвращает объект/список объектов (какого типа? как это выглядит?), в котором для каждого из ключей будут храниться все числа вошедшие в соответствующие интервал.
Да, правильно.

Цитата Сообщение от Dr2 Посмотреть сообщение
Для каждого из этих объектов Select считает длину (то есть все значения, хранимые внутри ключа?) и возвращает её, это и будет частота вхождения числа в интервал.
Количество элементов в группе. В остальном правильно.
1
Модератор
Эксперт .NET
10893 / 7733 / 2095
Регистрация: 21.04.2018
Сообщений: 23,266
Записей в блоге: 2
31.07.2019, 09:00 11
Цитата Сообщение от Dr2 Посмотреть сообщение
GroupBy возвращает объект/список объектов (какого типа? как это выглядит?)
IGrouping<TKey,TSource> см.
https://docs.microsoft.com/ru-... mework-4.8
https://professorweb.ru/my/LIN... l2/2_8.php
https://metanit.com/sharp/tutorial/15.6.php
1
Модератор
Эксперт .NET
10893 / 7733 / 2095
Регистрация: 21.04.2018
Сообщений: 23,266
Записей в блоге: 2
01.08.2019, 00:29 12
Dr2, ошибка в группировке!
C#
10
11
// Массив распределения по диапазонам - получение через группировку
List<int> groupFreq = list.GroupBy(x => (int) ((x-min)/rangeSize)).Select(x => x.Count).ToList();
1
1 / 1 / 0
Регистрация: 22.12.2014
Сообщений: 42
01.08.2019, 02:21  [ТС] 13
Цитата Сообщение от Элд Хасп Посмотреть сообщение
IGrouping<TKey,TSource> ]
Здесь ошибка
CS0411 Аргументы типа для метода "Enumerable.Select<TSource, TResult>(IEnumerable<TSource>, Func<TSource, TResult>)" не могут определяться по использованию. Попытайтесь явно определить аргументы типа.
C#
1
return Numbers.GroupBy(x => (int)((x - min) / rangeSize)).Select(x => x.Count).ToList();
Насколько я понял
GroupBy возвращает объект типа IEnumerable<IGrouping<K, Т>>
Select принимает объект типа IEnumerable<T>

И я должен как-то объяснить компилятору, что x в Select(x => x.Count) является объектом IGrouping<K, Т>

Без селекта вроде работает:
C#
1
2
3
4
5
6
7
IEnumerable<IGrouping<int, double>> GroupedNumbers = Numbers.GroupBy(x => (int)((x - min) / rangeSize));
 
            List<int> Frequencies = new List<int>();
            foreach (IGrouping<int, double> Groupe in GroupedNumbers)
            {
                Frequencies.Add(Groupe.Count());
            }
0
187 / 100 / 19
Регистрация: 15.09.2011
Сообщений: 801
01.08.2019, 02:36 14
Dr2, есть вариант для творчества - не используйте готовые решения - создайте форму, которая принимает массив, а на форме рисуйте линии самостоятельно - сделайте UserControl - будет быстрее чем разбираться в любом готовом решении и интереснее.
0
Модератор
Эксперт .NET
10893 / 7733 / 2095
Регистрация: 21.04.2018
Сообщений: 23,266
Записей в блоге: 2
01.08.2019, 10:42 15
Цитата Сообщение от Dr2 Посмотреть сообщение
Здесь ошибка
Писал здесь на смарте.
Компа под рукой нет.
Кажется, скобка перед Select пропущена.

Добавлено через 1 минуту
А нет - нормально.

Добавлено через 1 минуту
Целиком код метода скиньте.

Добавлено через 8 минут
Дошло! Count не свойство , а метод!
C#
1
return Numbers.GroupBy(x => (int)((x - min) / rangeSize)).Select(x => x.Count()).ToList();
1
1 / 1 / 0
Регистрация: 22.12.2014
Сообщений: 42
05.08.2019, 00:16  [ТС] 16
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Дошло! Count не свойство , а метод!
Дьявол кроется в деталях.

Пришлось добавить еще сортировку перед группировкой, иначе границы интервалов будут выбираться в случайном порядке.
C#
1
2
            Numbers.Sort();
            return Numbers.GroupBy(x => (int)((x - min) / rangeSize)).Select(x => x.Count()).ToList();
Миниатюры
Гистограмма частот  
0
Модератор
Эксперт .NET
10893 / 7733 / 2095
Регистрация: 21.04.2018
Сообщений: 23,266
Записей в блоге: 2
05.08.2019, 00:23 17
Цитата Сообщение от Dr2 Посмотреть сообщение
Пришлось добавить еще сортировку перед группировкой, иначе границы интервалов будут выбираться в случайном порядке.
Если делать через LINQ, то лучше так
C#
1
Numbers.GroupBy(x => (int)((x - min) / rangeSize)).OrderBy(x => x.Key).Select(x => x.Count()).ToList();
Добавлено через 2 минуты
Но возможен такой баг. Не знаю насколько он для вас существенен.
Если будет интервал в котором нет ни одного значения, то в LINQ группировке не будет создано такой группы.
1
1 / 1 / 0
Регистрация: 22.12.2014
Сообщений: 42
05.08.2019, 00:27  [ТС] 18
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Если делать через LINQ, то лучше так
C#
1
Numbers.GroupBy(x => (int)((x - min) / rangeSize)).OrderBy(x => x.Key).Select(x => x.Count()).ToList();
Поставил сортировку перед группировкой:
C#
1
return Numbers.OrderBy(x => x).GroupBy(x => (int)((x - min) / rangeSize)).Select(x => x.Count()).ToList();
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Но возможен такой баг. Не знаю насколько он для вас существенен.
Если будет интервал в котором нет ни одного значения, то в LINQ группировке не будет создано такой группы.
Вообще я все это затеял, чтобы посмотреть как работает алгоритм получения нормально распределенных чисел, дальнейшую шлифовку не предполагаю.
0
Модератор
Эксперт .NET
10893 / 7733 / 2095
Регистрация: 21.04.2018
Сообщений: 23,266
Записей в блоге: 2
05.08.2019, 00:43 19
Цитата Сообщение от Dr2 Посмотреть сообщение
Поставил сортировку перед группировкой:
По результату разницы не будет.
1
05.08.2019, 00:43
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
05.08.2019, 00:43

Гистограмма с вариабельным числом столбцов
Собираюсь работать с разными массивами выборок, поэтому число столбцов будет скорее всего меняться....

Гистограмма изображения по компонентам RGB
Здравствуйте! Пытаюсь построить гистограмму по трём цветовым компонентам из исходного изображения....

Двумерный массив из слов и их частот
Доброго времени суток! пытаюсь сделать массив из слов и их частот. Сначала текст разбиваю на...

Получить таблицу частот символов в тексте
написать консольное приложение на языке c#, которое позволит получить таблицу частот символов в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru