Шаг 50.
Однострочники Python. Наука о данных. Поиск лучше всего продающихся наборов с помощью промежуточного анализа ассоциаций

    На этом шаге мы продолжим знакомство с анализом ассоциаций.

    Исследуем анализ ассоциаций более подробно.

Общее описание

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

    Вы уже знаете все, что нужно для решения данной задачи, поэтому приступим!

Код

    Следующий однострочник предназначен для поиска двух чаще всего приобретаемых вместе товаров (пример 3.30).


Пример 3.30. Однострочное решение, использующее лямбда-функцию в качестве параметра key функции max(), списковое включение и булевы операторы с транслированием
## Зависимости
import numpy as np

## Данные: каждая строка соответствует корзине для покупок конкретного покупателя
## строка = [курс 1, курс 2, эл. книга 1, эл. книга 2]
## значение 1 означает, что товар был куплен
basket = np.array([[0, 1, 1, 0],
                   [0, 0, 0, 1],
                   [1, 1, 0, 0],
                   [0, 1, 1, 1],
                   [1, 1, 1, 0],
                   [0, 1, 1, 0],
                   [1, 1, 0, 1],
                   [1, 1, 1, 1]])

## Однострочник (разбит на две строки)
copurchases = [(i, j, np.sum(basket[:, i] + basket[:, j] == 2))
               for i in range(4) for j in range(i + 1, 4)]

## Результат
print(max(copurchases, key=lambda x: x[2]))
Архив с файлом можно взять здесь.

    Какими же будут результаты выполнения этого однострочного решения?

Принцип работы

    Массив данных состоит из данных о покупках, по одной строке на покупателя и по столбцу на товар. Наша задача - получить список кортежей, каждый из которых описывает конкретное сочетание товаров и частоту покупки этих товаров вместе. Первые два значения кортежа в каждом элементе списка должны быть индексами столбцов (сочетания двух товаров), а третье должно отражать число раз, когда они покупались вместе. Например, кортеж (0, 1, 4) означает, что покупатели, приобретавшие товар 0, также 4 раза покупали товар 1.

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

## Однострочник (разбит на две строки)
copurchases = [(i, j, np.sum(basket[:, i] + basket[:, j] == 2))
               for i in range(4) for j in range(i + 1, 4)]

    Как видно из внешней формы [(..., ..., ...) for ... in ... for ... in ...], мы создали список кортежей с помощью спискового включения (см. 13 шаг). Нас интересуют все уникальные сочетания индекса столбца массива с четырьмя столбцами. Вот результат одной только внешней части нашего однострочника:

print([(i, j) for i in range(4) for j in range(i+1, 4)])
# [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]

    Итак, в списке содержится шесть кортежей, все - уникальные сочетания индексов столбцов.

    Теперь можно заняться и третьим элементом кортежа: количеством раз, когда товары i и j покупали вместе:

np.sum(basket[:,i] + basket[:,j] == 2)

    Мы выделяем оба столбца i и j из исходного массива NumPy с помощью срезов. А затем складываем их поэлементно. И проверяем поэлементно в полученном массиве, равна ли сумма 2, что означает наличие 1 в обоих столбцах, а значит, и то, что были куплены оба товара. Результат представляет собой булев массив, в котором значения True соответствуют покупке обоих товаров вместе одним покупателем.

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

print(copurchases)
# [(0, 1, 4), (0, 2, 2), (0, 3, 2), (1, 2, 5), (1, 3, 3), (2, 3, 2)]

    Теперь осталось только найти два товара, которые покупали вместе чаще всего: ## Результат print(max(copurchases, key= lambda x: x[2])) Для поиска наибольшего элемента списка мы воспользовались функцией max(). Мы описали ключевую функцию, принимающую на входе кортеж и возвращающую третье значение кортежа (количество одновременных покупок), а затем нашли максимальное из этих значений. Результат выполнения однострочника выглядит следующим образом:

## Результат
print(max(copurchases, key=lambda x: x[2]))
# (1, 2, 5)

    Второй и третий товары покупали вместе пять раз. Ни одно из прочих сочетаний товаров не достигло таких показателей. Следовательно, можете смело сказать начальнику, что нужно стараться дополнительно продать товар 2 при продаже товара 1, и наоборот.

    Итак, вы узнали о разнообразных базовых возможностях как Python, так и NumPy, в частности о транслировании, списковом включении, лямбда-функциях и ключевых функциях. Зачастую своей выразительностью код Python обязан как раз сочетанию множества различных элементов языка, функций и трюков.

    На следующем шаге мы подведем некоторые итоги.




Предыдущий шаг Содержание Следующий шаг