Еще один способ вычисления медианы запросом 1С

09.08.21

Разработка - Запросы

Вниманию сообщества предлагается еще один способ расчета медианы числового ряда одним пакетным запросом 1С.

Гуглинг и инфостартинг не выдали автору статьи ответа – был ли этот способ когда-либо реализован на языке запросов 1С или нет. Если описание реализации такого способа для 1С уже есть – прошу ссылку казать в комментариях.

 
Лирическое отступление

В начале, как и положено -

Сухая теория

Согласно википедии, у понятия «медиана» есть два определения:

  1. Медиана (от лат. mediāna «середина») набора чисел — число, которое находится в середине этого набора, если его упорядочить по возрастанию, то есть такое число, что половина из элементов набора не меньше него, а другая половина не больше.
  2. Медиана набора чисел — это число, сумма расстояний (или, если более строго, модулей) от которого до всех чисел из набора минимальна

В дальнейших рассуждениях будем опираться на первое определение. Но не только потому, что оно проще в восприятии.

Алгоритм вычисления медианы по этому определению прост и состоит из следующих шагов:

  1. пусть нам дан некоторый числовой ряд из N чисел
  2. упорядочиваем этот ряд по возрастанию значений
  3. если N – нечетное, то
    1. вычисляем индекс i = Целое(1 + N/2)
    2. находим число ni, стоящее на месте с индексом i
    3. найденное число и есть искомая медиана
  4. если N – четное
    1. вычисляем два индекса – i и j, где i = N / 2, j = i + 1
    2. и вот тут есть три варианта:
      1. объявляем медианой число ni
      2. объявляем медианой число nj
      3. объявляем медианой среднее арифметическое этих чисел
 
Примеры

 В этих примерах будем считать, что индексация ряда начинается с 1

Пример ряда с нечетным количеством элементов

  1. Пусть дан числовой ряд {7, 15, 6, 8, 7, 7, 15}
  2. упорядочим ряд по возрастанию значений: {6, 7, 7, 7, 8, 15, 15}
  3. ряд содержит 7 чисел (N = 7), значит i = Целое (1 + 7/2) = 4
  4. медиана ряда - число i4 = 7

Пример ряда с четным количеством элементов

  1. Пусть дан числовой ряд {7, 15, 6, 8, 7, 7, 20, 15}
  2. упорядочим ряд по возрастанию значений: {6, 7, 7, 7, 8, 15, 15, 20}
  3. ряд содержит 8 чисел (N = 8), значит
    1. i = 8/2 = 4
    2. j = i + 1 = 5
  4. медианой этого числового ряда могут быть следующие числа:
    1. i4 = 7
    2. i5 = 8
    3. Среднее(7, 8) = (7 + 8) / 2 = 7.5

Теоретически вроде просто.

Но на практике при попытке реализации этого алгоритма методом «в лоб» на языке запросов 1С возникает одна непростая задача – индексация элементов ряда: в языке запросов 1С нет легких и быстрых способов пронумеровать элементы числового ряда. Задача нумерации элементов ряда еще более осложняется, если в этом ряду есть дубликаты.
Способ, предлагаемый вниманию сообщества, избавляет нас от необходимости индексировать числовой ряд.

Описание предлагаемого способа

Даже больше - этот способ не предусматривает упорядочивание ряда по возрастанию значений его элементов!

Что же такого хитрого в этом способе?

Все дело в индексах элементов упорядоченного числового ряда.

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

Для рассмотрения возьмем числовой ряд из первого примера - {7, 15, 6, 8, 7, 7, 15}.

И проделаем с ним следующие манипуляции:

- упорядочим - {6, 7, 7, 7, 8, 15, 15}.

- проиндексируем упорядоченный ряд:

n1 = 6

n2 = 7

n3 = 7

n4 = 7

n5 = 8

n6 = 15

n7 = 15

- выделим уникальные элементы ряда: {6, 7, 8 ,15}

- определим диапазоны индексов, которые занимают уникальные элементы ряда в упорядоченном ряду:

6 – [1, 1]

7 – [2, 4]

8 – [5, 5]

15 – [6, 7].

И вот тут мне кажется, что Вы, мой внимательный читатель, уже поняли основную суть!

Совершенно верно: зная индекс среднего элемента ряда нам необходимо всего лишь определить:

- в какой диапазон этот индекс попадает

- и какой элемент ряда занимает этот диапазон.

Т.е. для нашего примера индекс среднего элемента упорядоченного ряда равен 4.

Этот индекс входит в диапазон [2, 4].

Число, занимающее этот диапазон – 7.

Это число – и есть медиана нашего числового ряда.

 

Подытожим – в предлагаемом способе для вычисления медианы нам необходимо всего лишь:

- иметь диапазоны индексов, которые занимают уникальные элементы ряда в упорядоченном ряду

- знать индекс среднего элемента ряда!

И то, и другое уже можно реализовать на языке запросов 1С.

От теории к практике

Настало время продемонстрировать запрос 1С, реализующий предложенный способ.

Небольшое уточнение: для ряда, содержащего четное количество элементов, предлагаемый запрос в качестве медианы вычисляет среднее арифметическое элементов ni и nj

Вот он:

ВЫБРАТЬ     7 КАК Элемент
ПОМЕСТИТЬ Ряд
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ    15
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ    6
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ    8
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ    7
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ    7
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ    15

;
////////////////////////////////////////////////////////////////////////////////

ВЫБРАТЬ
    КОЛИЧЕСТВО(Ряд.Элемент) КАК Длина
ПОМЕСТИТЬ ДлинаРяда
ИЗ
    Ряд КАК Ряд
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВЫРАЗИТЬ((ДлинаРяда.Длина - 1) / 2 - 0.1 КАК ЧИСЛО(19, 0)) КАК Индекс
ПОМЕСТИТЬ ИндексМедианногоЭлемента
ИЗ
    ДлинаРяда КАК ДлинаРяда

ОБЪЕДИНИТЬ

ВЫБРАТЬ
    ВЫРАЗИТЬ((ДлинаРяда.Длина - 1) / 2 КАК ЧИСЛО(19, 0))
ИЗ
    ДлинаРяда КАК ДлинаРяда
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Ряд.Элемент КАК Элемент,
    КОЛИЧЕСТВО(Ряд.Элемент) КАК Количество
ПОМЕСТИТЬ СтатистикаРяда
ИЗ
    Ряд КАК Ряд

СГРУППИРОВАТЬ ПО
    Ряд.Элемент
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Окончание.Элемент КАК Элемент,
    ЕСТЬNULL(СУММА(Начало.Количество), 0) КАК НачальныйИндекс,
    ЕСТЬNULL(СУММА(Начало.Количество), 0) + Окончание.Количество - 1 КАК КонечныйИндекс
ПОМЕСТИТЬ ИндексыЭлементов
ИЗ
    СтатистикаРяда КАК Начало
        ПРАВОЕ СОЕДИНЕНИЕ СтатистикаРяда КАК Окончание
        ПО Начало.Элемент < Окончание.Элемент

СГРУППИРОВАТЬ ПО
    Окончание.Элемент,
    Окончание.Количество
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    СРЕДНЕЕ(ИндексыЭлементов.Элемент) КАК Элемент
ИЗ
    ИндексМедианногоЭлемента КАК ИндексМедианногоЭлемента
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ИндексыЭлементов КАК ИндексыЭлементов
        ПО (ИндексМедианногоЭлемента.Индекс МЕЖДУ ИндексыЭлементов.НачальныйИндекс И ИндексыЭлементов.КонечныйИндекс)

 

Запрос достаточно прост и вряд ли нуждается в комментировании.

Медиана запрос интервал статистика

См. также

Инструментарий разработчика Роли и права Запросы СКД Программист Руководитель проекта Платформа 1С v8.3 Управляемые формы Запросы Система компоновки данных Платные (руб)

Инструменты для разработчиков 1С 8.3: Infostart Toolkit. Автоматизация и ускорение разработки на управляемых формах. Легкость работы с 1С.

12000 руб.

02.09.2020    169341    937    403    

905

Запросы Программист Бесплатно (free)

Увидел cheatsheet по SQL и захотелось нарисовать подобное, но про запросы.

18.10.2024    11402    sergey279    18    

65

Запросы Программист Платформа 1С v8.3 Запросы Конфигурации 1cv8 Бесплатно (free)

Столкнулся с интересной ситуацией, которую хотел бы разобрать, ввиду её неочевидности. Речь пойдёт про использование функции запроса АВТОНОМЕРЗАПИСИ() и проблемы, которые могут возникнуть.

11.10.2024    6347    XilDen    36    

83

Запросы Программист Запросы Бесплатно (free)

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

16.08.2024    9077    user1840182    5    

28

Математика и алгоритмы Запросы Программист Платформа 1С v8.3 Запросы Бесплатно (free)

Рассмотрим быстрый алгоритм поиска дублей с использованием hash функции по набору полей шапки и табличных частей.

08.07.2024    2732    ivanov660    9    

22

Запросы СКД Программист Стажер Система компоновки данных Россия Бесплатно (free)

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

15.05.2024    10224    implecs_team    6    

48

Запросы Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Часто поступают задачи по произвольному распределению общих сумм. После распределения иногда пропадают копейки. Суть решения добавить АвтоНомерЗаписи() в ВТ распределения, и далее используя функции МАКСИМУМ или МИНИМУМ можем положить разницу копеек в первую или последнюю строку знаменателя распределения.

11.04.2024    3626    andrey_sag    10    

38
Оставьте свое сообщение