Как динамически генерировать полосы/группы данных с одинаковыми числами в каждом?

StackOverflow https://stackoverflow.com/questions/4520230

  •  12-10-2019
  •  | 
  •  

Вопрос

Я хочу динамически генерировать полосы, которые затем будут сгруппированы в отчетах.

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

Например, предположим, что у вас была зарплата для большой группы людей:

  • Самая низкая оплаченная зарабатывает 12 000 фунтов стерлингов в год, а самый высокий зарабатывает 3 000 000 фунтов стерлингов
  • Поэтому я разделил это на 10 полос аналогичного размера: (3 миллиона фунтов стерлингов - 12 тыс. Фунтов стерлингов) / 10 = £ 298800
  • Итак, моя первая группа стоит от 12 до 310 800 фунтов стерлингов и получает тысячи людей
  • Моя вторая группа стоит от 310 тысяч фунтов стерлингов и имеет несколько сотен
  • У любой другой группы есть несколько человек в каждой

Так что это на самом деле не очень полезно. Если бы я был вручную создать группы, которые я бы хотел примерно аналогичных цифр в каждом, что-то вроде: 12 тыс. Фунтов стерлингов, 14 тыс. Фунтов стерлингов, 18 тысяч фунтов стерлингов, 25 тыс. Фунтов стерлингов, 25-35 тыс. Фунтов стерлингов, ..., £ 1,5- 3 миллиона фунтов стерлингов

Это только один пример - может быть много разных распределений.

Я ищу алгоритм для генерации полос, поэтому пользователи вводят, сколько групп они хотят, и данные будут сгруппированы в столько полос с одинаковым числом в каждой.

Беспочка должна быть быстрой - я не могу просто пройти через весь набор данных.

Приложение C# в верхней части SQL, но решения от других языков приветствуются.

Это было полезно?

Решение

Я думаю, вы спрашиваете о том, как запросить существующий набор данных в «группах» ...

Если это правда, то Oracle поддерживает функции NTILE Agagerate для этого. Должны быть эквиваленты в других реализациях SQL.

Другие советы

Вы смотрели на Ntile? SQL Server и большинство СУБД поддерживают его.

Например:

select b.band, count(*), min(b.valuefield), max(b.valuefield)
from ( 
    select ntile(10) over (order by valuefield) as 'band', valuefield
    from table ) b
group by b.band

Вы смотрите на проблему с неправильной точки зрения. Вместо того, чтобы смотреть на зарплату, посмотрите на упорядоченное положение человека в сортированном диапазоне зарплат. Отложите алгоритм на секунду и подумайте об этом математически.

Возьмите всех своих людей и сортируйте их по зарплате. Теперь последовательно насчиская их с 1 на n до N, последний с самой высокой зарплатой. Если вам нужны M группы, то каждая группа содержит N/M. Таким образом, первая полоса зарплаты переходит от 0 до человека [N/M] .salary, вторая идет оттуда к человеку [2*n/M] .salary и т. Д.

В C# вы можете сделать это довольно эффективно в LINQ. Что-то вроде этого. Это непроверенный код, это концепция, а не окончательное решение, вероятно, есть некоторые проблемы с условием края, о которых я не думал правильно.

List<int> GetBands(int numBands)
{
    using(var db = new MyContext())    
    {
        var list SalaryBands = new List<int>();
        var count = db.People.Count();
        var salaries = db.People.OrderBy(item => item.Salary)
                                .Select(item => item.Salary);
        int skipCount = count / numBands;
        for(int segmentNum = 0; segmentNum < numBands; segmentCount++)
        {
            salaries = salaries.Skip(skipCount);
            salaryBands.Add(salaries.First());
        }
        return salaryBands;
    }
}

Первое наблюдение, вам нужен логический график, в отличие от прямой линейной.

Второе наблюдение: я обычно строю большие наборы данных выборки (сродни вашим примеру), а затем ищу свои общие факторы и получаю формальную систему из фактических данных. Можете ли вы создать еще несколько сценариев?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top