Нашли ошибку?
Скачать чистый
урок 2 из 4≈ 20 минупражнения: 0 из 4

Частоты и доли

От количеств к долям и процентам: value_counts(normalize=True); как пропуски меняют доли; накопленная сумма cumsum и вопросы «сколько заказов доставлено за неделю» и «сколько покупателей дают половину продаж».

Python запустится при первом выполнении

«948 строк из Москвы» — много это или мало? Число само по себе ни о чём не говорит, пока не знаешь, сколько всего. Поэтому количества обычно превращают в доли: 948 из 2448 — это 39 %.

Доли вместо количеств

value_counts считает, сколько раз встречается каждое значение:

[ ]Строк по каналам
import pandas as pd

orders = pd.read_csv("data/shop_orders.csv")
orders["channel"].value_counts()
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
channel
сайт           1137
приложение      684
маркетплейс     627
Name: count, dtype: int64

С параметром normalize=True он сразу делит на общее число и возвращает доли от 0 до 1:

[ ]Доли каналов
orders["channel"].value_counts(normalize=True)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
channel
сайт           0.464461
приложение     0.279412
маркетплейс    0.256127
Name: proportion, dtype: float64

Доли в сумме дают единицу. Чтобы получить проценты, умножают на 100 и округляют:

[ ]Проценты с одним знаком
(orders["channel"].value_counts(normalize=True) * 100).round(1)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
channel
сайт           46.4
приложение     27.9
маркетплейс    25.6
Name: proportion, dtype: float64
[ ]Упражнение 1Проценты по категориям решено

Сохраните в category_pct процент строк каждой категории (столбец category), округлённый до одного знака после запятой. В coffee_pct сохраните процент кофе.

category_pct = ...
coffee_pct = ...

Доля среди кого?

С пропусками нужно быть внимательным. value_counts пропуски не считает — и доли получаются среди непустых значений:

[ ]Доли оценок доставки
delivery = pd.read_csv("data/delivery_h1.csv")
delivery["rating"].value_counts(normalize=True).sort_index()
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
rating
1.0    0.013233
2.0    0.090737
3.0    0.279773
4.0    0.423440
5.0    0.192817
Name: proportion, dtype: float64

«42 % четвёрок» — это доля среди тех, кто оценку поставил. А поставили её не все. Параметр dropna=False добавляет пропуски отдельной строкой, и доли считаются уже среди всех заказов:

[ ]То же — с пропусками
delivery["rating"].value_counts(normalize=True, dropna=False).sort_index()
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
rating
1.0    0.008578
2.0    0.058824
3.0    0.181373
4.0    0.274510
5.0    0.125000
NaN    0.351716
Name: proportion, dtype: float64

Теперь четвёрок 27 %, а треть заказов — без оценки. Оба расчёта верны; важно знать, какой из них перед вами, и подписывать: «42 % среди оценивших».

[ ]Упражнение 2Высокие оценки решено

Сохраните в rating_share доли оценок среди поставленных. Затем посчитайте долю высоких оценок (4 и 5) двумя способами: high_among_rated — среди заказов с оценкой, high_among_all — среди всех заказов.

rating_share = ...
high_among_rated = ...
high_among_all = ...

62 % или 40 % — разница принципиальная. Первое число говорит «оценившие довольны», второе — «высокую оценку поставили в двух заказах из пяти».

Пояснение с ответом появится, когда решите упражнение «Высокие оценки».

Накопленная сумма

Метод cumsum (cumulative sum) заменяет каждое значение суммой всех значений от начала до него:

[ ]3, 3+1, 3+1+4, 3+1+4+2
steps = pd.Series([3, 1, 4, 2])
steps.cumsum()
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
0     3
1     4
2     8
3    10
dtype: int64
Вопрос

Что выведет print(pd.Series([1, 2, 3]).cumsum().tolist())?

Накопленная сумма долей отвечает на вопросы вида «в какой доле строк купили не больше N штук». Доли нужно сначала выстроить по количеству — sort_index:

[ ]Доля строк, где купили N штук или меньше
quantity_share = orders["quantity"].value_counts(normalize=True).sort_index()
quantity_share.cumsum().round(3).head(5)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
quantity
1    0.406
2    0.728
3    0.873
4    0.931
5    0.960
Name: proportion, dtype: float64

Читается так: в 41 % строк одна штука, в 73 % — не больше двух, в 93 % — не больше четырёх.

[ ]Упражнение 3Доставка за неделю решено

Сохраните в cum_days накопленную долю заказов по сроку доставки (столбец days): сроки по возрастанию. В within_week сохраните долю заказов, доставленных за 7 дней или быстрее, в later — долю остальных.

cum_days = ...
within_week = ...
later = ...

Сколько товаров дают половину покупок

Здесь порядок «от частого к редкому» как раз нужен. Накопленная доля по убыванию показывает, какую часть итога дают несколько лидеров:

[ ]Накопленная доля строк по товарам
product_share = orders["product"].value_counts(normalize=True)
product_share.cumsum().round(3).head(7)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
product
Колумбия 250 г            0.089
Кофе без кофеина 250 г    0.176
Эфиопия 250 г             0.262
Травяной сбор 50 г        0.334
Зелёный чай 100 г         0.406
Чёрный чай 100 г          0.476
Бразилия 1 кг             0.545
Name: proportion, dtype: float64

Первый товар — 9 % строк, первые два — 18 %, первые шесть — 48 %. Считать глазами не обязательно: число значений, уместившихся в половину, даёт маска.

[ ]Товаров до отметки 50 %
print((product_share.cumsum() <= 0.5).sum(), "из", len(product_share))
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
6 из 20

Шесть товаров из двадцати дают почти половину покупок. Такая неравномерность встречается очень часто: небольшая часть товаров, клиентов или причин отвечает за большую часть результата.

[ ]Упражнение 4Ядро покупателей решено

Сохраните в buyer_share долю строк каждого покупателя (столбец customer_id), в cum_buyers — накопленную долю от самого активного покупателя к самому редкому. В core сохраните, сколько покупателей укладывается в первые 50 % строк, а в core_share — какую долю от всех покупателей они составляют.

buyer_share = ...
cum_buyers = ...
core = ...
core_share = ...

Пятая часть покупателей делает половину покупок — магазину стоит знать этих людей по именам.

Пояснение с ответом появится, когда решите упражнение «Ядро покупателей».

Итоги

  • value_counts(normalize=True) — доли от 0 до 1; * 100 и round — проценты.
  • Пропуски в доли не входят; dropna=False считает их отдельной строкой. Всегда уточняйте, среди кого доля.
  • cumsum() — накопленная сумма; с долями отвечает на вопросы «не больше N» и «сколько лидеров дают половину».
  • Перед cumsum проверьте порядок строк: по значению (sort_index) или по частоте.

Подробнее в справочнике

Нашли ошибку?