Найти тему

Numpy: вычисление разницы каждого элемента вектора с каждым

Продолжаем серию статей по numpy-программированию. Для удобства читателей собрал список моих статей по этой теме:

  1. Numpy для продвинутых
  2. Продолжаем numpy-программирование для продвинутых
  3. Создаем скользящее окно без циклов
  4. Перебор значений без циклов
  5. Поиск локального максимума с помощью numpy-программирования
  6. Numpy для работы с координатами прямоугольников
  7. Отличие матричного программирования от numpy-программирования.

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

Для лучшего понимания приведем пример, для чего возьмем следующий вектор v: [34, 77, 67, 61, 88, 36, 7, 41, 29, 38]. Разница второго элемента с первым: 43, третьего с первым: 33, четвертого с первым: 27 и так далее. С похожим перебором мы сталкивались в статье "Перебор значений без циклов", можно воспользоваться этим способом, но тогда не было бы смысла писать эту статью.

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

Матрица разницы элементов вектора
Матрица разницы элементов вектора

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

Матрица сумм элементов вектора
Матрица сумм элементов вектора

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

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

Функция triu_indices позволяет обойти проблему лишних вычислений. Эта функция возвращает два вектора индексов, которые образуют верхнюю половину от диагонали матрицы:

Вычисление верхней половины матрицы разницы всех элементов вектора v
Вычисление верхней половины матрицы разницы всех элементов вектора v

Первым параметром этой функции является количество элементов квадратной матрицы, k - сдвиг от диагонали (ведь нам сама диагональ не нужна). Полученные вектора подставляем как индексы (они ими и являются) в исходный вектор. Вместо функции diff можно использовать просто выражение v[b] - v[a]. Для получения нижней части достаточно поменять a и b местами.

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

Жонглер даннымиПросто о сложных вещах: получение, обработка и анализ данных