До сих пор мы только читали таблицы. Теперь начнём их менять — и первым делом добавлять столбцы: выручку,
маржу, долю. В этом модуле появится ещё одна таблица магазина — справочник товаров data/products.csv:
20 товаров с ценой (price) и себестоимостью (cost).
import pandas as pd
products = pd.read_csv("data/products.csv")
products.head()| product_id | name | category | price | cost | |
|---|---|---|---|---|---|
| 0 | P01 | Эспрессо-смесь 1 кг | Кофе | 1450 | 870 |
| 1 | P02 | Колумбия 250 г | Кофе | 690 | 380 |
| 2 | P03 | Эфиопия 250 г | Кофе | 790 | 430 |
| 3 | P04 | Бразилия 1 кг | Кофе | 1290 | 780 |
| 4 | P05 | Кофе без кофеина 250 г | Кофе | 720 | 410 |
Новый столбец
Столбец добавляют присваиванием: слева — таблица и название нового столбца в скобках, справа — значения.
products["margin"] = products["price"] - products["cost"]
products.head()| product_id | name | category | price | cost | margin | |
|---|---|---|---|---|---|---|
| 0 | P01 | Эспрессо-смесь 1 кг | Кофе | 1450 | 870 | 580 |
| 1 | P02 | Колумбия 250 г | Кофе | 690 | 380 | 310 |
| 2 | P03 | Эфиопия 250 г | Кофе | 790 | 430 | 360 |
| 3 | P04 | Бразилия 1 кг | Кофе | 1290 | 780 | 510 |
| 4 | P05 | Кофе без кофеина 250 г | Кофе | 720 | 410 | 310 |
Справа может стоять любой Series той же длины — обычно результат арифметики или сравнения. Если справа одно значение, им заполнится весь столбец:
products["currency"] = "RUB"
products["is_costly"] = products["price"] > 1000
products.head(3)| product_id | name | category | price | cost | margin | currency | is_costly | |
|---|---|---|---|---|---|---|---|---|
| 0 | P01 | Эспрессо-смесь 1 кг | Кофе | 1450 | 870 | 580 | RUB | True |
| 1 | P02 | Колумбия 250 г | Кофе | 690 | 380 | 310 | RUB | False |
| 2 | P03 | Эфиопия 250 г | Кофе | 790 | 430 | 360 | RUB | False |
Новый столбец всегда встаёт последним.
Добавьте в таблицу orders столбец revenue — выручку каждой строки: цена, умноженная на количество.
orders["revenue"], справа — произведение столбцов price и quantity.Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
orders = pd.read_csv("data/shop_orders.csv")
# добавьте в таблицу orders столбец revenueУпражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
orders = pd.read_csv("data/shop_orders.csv")
orders["revenue"] = orders["price"] * orders["quantity"]Перезаписать столбец
Если столбец с таким названием уже есть, присваивание его заменит. Превратим маржу из рублей в долю цены:
products["margin"] = products["margin"] / products["price"]
products[["name", "price", "cost", "margin"]].head(3)| name | price | cost | margin | |
|---|---|---|---|---|
| 0 | Эспрессо-смесь 1 кг | 1450 | 870 | 0.400000 |
| 1 | Колумбия 250 г | 690 | 380 | 0.449275 |
| 2 | Эфиопия 250 г | 790 | 430 | 0.455696 |
Длинные дроби читать неудобно. Метод round округляет значения Series до нужного числа знаков после запятой:
products["margin"] = products["margin"].round(2)
products[["name", "price", "cost", "margin"]].head(3)| name | price | cost | margin | |
|---|---|---|---|---|
| 0 | Эспрессо-смесь 1 кг | 1450 | 870 | 0.40 |
| 1 | Колумбия 250 г | 690 | 380 | 0.45 |
| 2 | Эфиопия 250 г | 790 | 430 | 0.46 |
Будьте осторожны с перезаписью: прежних значений больше нет. Если запустить ячейку с делением ещё раз, доля разделится на цену повторно — и получится бессмыслица. Когда столбец меняет смысл, лучше дать новому своё название.
Добавьте в таблицу products столбец markup — наценку: цена, делённая на себестоимость, с округлением до одного знака
после запятой.
products["price"] / products["cost"] — возьмите в скобки и вызовите .round(1).Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
# добавьте в таблицу products столбец markupУпражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
products["markup"] = (products["price"] / products["cost"]).round(1)assign: столбец в новой таблице
Присваивание меняет саму таблицу. Метод assign поступает иначе: возвращает новую таблицу с добавленным
столбцом, а исходную оставляет как была. Название столбца пишут как имя параметра — без кавычек:
with_vat = products.assign(price_vat=products["price"] * 1.2)
with_vat[["name", "price", "price_vat"]].head(3)| name | price | price_vat | |
|---|---|---|---|
| 0 | Эспрессо-смесь 1 кг | 1450 | 1740.0 |
| 1 | Колумбия 250 г | 690 | 828.0 |
| 2 | Эфиопия 250 г | 790 | 948.0 |
print("price_vat" in products.columns)
print("price_vat" in with_vat.columns)False True
assign удобен, когда столбец нужен на один раз или когда исходную таблицу портить нельзя.
rename и drop
rename переименовывает столбцы по словарю «старое название → новое»:
products.rename(columns={"category": "group", "cost": "cost_rub"}).head(2)| product_id | name | group | price | cost_rub | margin | currency | is_costly | markup | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | P01 | Эспрессо-смесь 1 кг | Кофе | 1450 | 870 | 0.40 | RUB | True | 1.7 |
| 1 | P02 | Колумбия 250 г | Кофе | 690 | 380 | 0.45 | RUB | False | 1.8 |
drop удаляет столбцы из списка:
products.drop(columns=["margin", "cost"]).head(2)| product_id | name | category | price | currency | is_costly | markup | |
|---|---|---|---|---|---|---|---|
| 0 | P01 | Эспрессо-смесь 1 кг | Кофе | 1450 | RUB | True | 1.7 |
| 1 | P02 | Колумбия 250 г | Кофе | 690 | RUB | False | 1.8 |
Оба метода, как и assign, возвращают новую таблицу. Исходная не изменилась — все столбцы на месте:
products.columnsIndex(['product_id', 'name', 'category', 'price', 'cost', 'margin', 'currency',
'is_costly', 'markup'],
dtype='str')Так ведут себя почти все методы pandas: они не меняют таблицу, а возвращают изменённую копию. Чтобы сохранить результат,
его нужно присвоить — новой переменной или той же: products = products.drop(columns=[...]).
t = pd.DataFrame({"a": [1, 2], "b": [3, 4], "c": [5, 6]})
t.drop(columns=["c"])
print(t.shape[1])Что выведет этот код?
drop вернул новую таблицу из двух столбцов, но её никуда не сохранили. В t по-прежнему три столбца. Чтобы удалить столбец из t, нужно t = t.drop(columns=["c"]).Сохраните в catalog таблицу products без столбцов currency и is_costly, в которой столбец name
переименован в product. Саму таблицу products не меняйте.
products.rename(columns={...}).drop(columns=[...]).Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
catalog = ...Упражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
catalog = products.rename(columns={"name": "product"}).drop(columns=["currency", "is_costly"])Столбец из нового столбца
Добавленный столбец — обычный столбец: его можно использовать в следующих вычислениях.
Магазин хочет давать скидку 5 %. Добавьте в orders столбец discount — 5 % от выручки строки (revenue)
и столбец to_pay — выручка минус скидка. В total_to_pay сохраните сумму столбца to_pay.
orders["discount"] = orders["revenue"] * 0.05.orders["to_pay"] = orders["revenue"] - orders["discount"]; сумма — .sum().Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
# добавьте в orders столбцы discount и to_pay
total_to_pay = ...Упражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
orders["discount"] = orders["revenue"] * 0.05
orders["to_pay"] = orders["revenue"] - orders["discount"]
total_to_pay = orders["to_pay"].sum()Итоги
таблица["новый"] = значениядобавляет столбец или заменяет существующий — меняет саму таблицу.round(n)округляет доnзнаков после запятой.assign(название=значения),rename(columns={...}),drop(columns=[...])возвращают новую таблицу; результат нужно сохранить.