Еще один способ вычисления медианы запросом 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 КАК КонечныйИндекс
ПОМЕСТИТЬ ИндексыЭлементов
ИЗ
    СтатистикаРяда КАК Начало
        ПРАВОЕ СОЕДИНЕНИЕ СтатистикаРяда КАК Окончание
        ПО Начало.Элемент < Окончание.Элемент

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

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

 

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

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

См. также

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

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

Набор инструментов программиста и специалиста 1С для всех конфигураций на управляемых формах. В состав входят инструменты: Консоль запросов, Консоль СКД, Консоль кода, Редактор объекта, Анализ прав доступа, Метаданные, Поиск ссылок, Сравнение объектов, Все функции, Подписки на события и др. Редактор запросов и кода с раскраской и контекстной подсказкой. Доработанный конструктор запросов тонкого клиента. Продукт хорошо оптимизирован и обладает самым широким функционалом среди всех инструментов, представленных на рынке.

10000 руб.

02.09.2020    128429    694    389    

744

Пропорциональное распределение в запросе с использованием АвтоНомерЗаписи()

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

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

11.04.2024    2549    andrey_sag    10    

31

Для чего используют конструкцию запроса "ГДЕ ЛОЖЬ" в СКД на примере конфигурации 1С:ERP

Запросы СКД Платформа 1С v8.3 Запросы Система компоновки данных 1С:ERP Управление предприятием 2 Бесплатно (free)

В типовых конфигурациях разработчики компании 1С иногда используют в отчетах, построенных на СКД, такую конструкцию, как "ГДЕ ЛОЖЬ". Такая конструкция говорит о том, что данные в запросе не будут получены совсем. Для чего же нужен тогда запрос?

13.02.2024    6227    KawaNoNeko    23    

26

Набор-объект для СКД по тексту или запросу

Запросы СКД Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Абонемент ($m)

Есть список полей в виде текста, или запрос - закидываем в набор СКД.

1 стартмани

31.01.2024    2254    2    Yashazz    0    

31

Запрос 1С copilot

Инструментарий разработчика Запросы Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Бесплатно (free)

Пишем на человеческом языке, что нам надо, и получаем текст запроса на языке 1С. Используются большие языковые модели (LLM GPT) от OpenAI или Яндекс на выбор.

15.01.2024    6959    32    mkalimulin    32    

53

PrintWizard: поддержка представлений ЗУП в конструкторе

Инструментарий разработчика Запросы Платформа 1С v8.3 Бесплатно (free)

Одной из интересных задач, стоящих в процессе разработки, была поддержка механизма представлений в ЗУП. Но не просто возможность исполнения запросов с ними. Основная проблема была в том, чтобы с ними было удобно работать, а именно: создавать, модифицировать и отлаживать. Кратко о том, что в итоге получилось...

14.12.2023    1992    vandalsvq    7    

29

Консоль запросов УФ 8.3.2.24.12 (мод от Dr.Zombi)

Инструментарий разработчика Запросы Платформа 1С v8.3 Управляемые формы Запросы Россия Абонемент ($m)

Работа с запросом и СКД, Полная поддержка пакетных запросов, временных таблиц. Главное скорость отладки запроса и данных, а красота вторична.

1 стартмани

07.12.2023    3448    52    DrZombi    54    

20

Объектная модель запроса "Схема запроса" 2

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

Далеко уже не новый тип данных "Схема запроса". Статья о том, как использовать его "попроще". Примеры создания текста запроса с нуля и изменение имеющегося запроса.

06.12.2023    5758    user1923546    26    

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