«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
Сохраните в category_pct процент строк каждой категории (столбец category), округлённый до одного знака
после запятой. В coffee_pct сохраните процент кофе.
orders["category"].value_counts(normalize=True) * 100 — всё выражение в скобки и .round(1).Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
category_pct = ...
coffee_pct = ...Упражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
category_pct = (orders["category"].value_counts(normalize=True) * 100).round(1)
coffee_pct = category_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 % среди оценивших».
Сохраните в rating_share доли оценок среди поставленных. Затем посчитайте долю высоких оценок (4 и 5)
двумя способами: high_among_rated — среди заказов с оценкой, high_among_all — среди всех заказов.
rating_share[4] + rating_share[5].delivery["rating"] >= 4: сравнение с пропуском даёт False, и заказ без оценки считается «не высоким».Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
rating_share = ...
high_among_rated = ...
high_among_all = ...Упражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
rating_share = delivery["rating"].value_counts(normalize=True)
high_among_rated = rating_share[4] + rating_share[5]
high_among_all = (delivery["rating"] >= 4).mean()62 % или 40 % — разница принципиальная. Первое число говорит «оценившие довольны», второе — «высокую оценку поставили в двух заказах из пяти».
Накопленная сумма
Метод cumsum (cumulative sum) заменяет каждое значение суммой всех значений от начала до него:
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:
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 % — не больше четырёх.
Сохраните в cum_days накопленную долю заказов по сроку доставки (столбец days): сроки по возрастанию.
В within_week сохраните долю заказов, доставленных за 7 дней или быстрее, в later — долю остальных.
delivery["days"].value_counts(normalize=True).sort_index().cumsum().cum_days[7]; остальные — 1 - within_week.Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
cum_days = ...
within_week = ...
later = ...Упражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
cum_days = delivery["days"].value_counts(normalize=True).sort_index().cumsum()
within_week = cum_days[7]
later = 1 - within_weekСколько товаров дают половину покупок
Здесь порядок «от частого к редкому» как раз нужен. Накопленная доля по убыванию показывает, какую часть итога дают несколько лидеров:
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 %. Считать глазами не обязательно: число значений, уместившихся в половину, даёт маска.
print((product_share.cumsum() <= 0.5).sum(), "из", len(product_share))6 из 20
Шесть товаров из двадцати дают почти половину покупок. Такая неравномерность встречается очень часто: небольшая часть товаров, клиентов или причин отвечает за большую часть результата.
Сохраните в buyer_share долю строк каждого покупателя (столбец customer_id), в cum_buyers — накопленную
долю от самого активного покупателя к самому редкому. В core сохраните, сколько покупателей укладывается
в первые 50 % строк, а в core_share — какую долю от всех покупателей они составляют.
orders["customer_id"].value_counts(normalize=True) и .cumsum().(cum_buyers <= 0.5).sum() — число покупателей; всего покупателей — len(buyer_share).Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
buyer_share = ...
cum_buyers = ...
core = ...
core_share = ...Упражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
buyer_share = orders["customer_id"].value_counts(normalize=True)
cum_buyers = buyer_share.cumsum()
core = (cum_buyers <= 0.5).sum()
core_share = core / len(buyer_share)Пятая часть покупателей делает половину покупок — магазину стоит знать этих людей по именам.
Итоги
value_counts(normalize=True)— доли от 0 до 1;* 100иround— проценты.- Пропуски в доли не входят;
dropna=Falseсчитает их отдельной строкой. Всегда уточняйте, среди кого доля. cumsum()— накопленная сумма; с долями отвечает на вопросы «не больше N» и «сколько лидеров дают половину».- Перед
cumsumпроверьте порядок строк: по значению (sort_index) или по частоте.