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

Склеить таблицы

pd.concat ставит таблицы друг под другом: выгрузки по полугодиям, файлы нескольких станций. Почему после склейки повторяются метки и зачем ignore_index; что бывает, когда столбцы разные; склейка столбцами.

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

Данные часто приходят частями: выгрузка за январь, выгрузка за февраль; файл по каждому филиалу. Столбцы у частей одинаковые, и перед анализом их нужно собрать в одну таблицу. Служба доставки «Кофейной лавки» присылает отчёт по полугодиям:

[ ]Два файла с одинаковыми столбцами
import pandas as pd

h1 = pd.read_csv("data/delivery_h1.csv")
h2 = pd.read_csv("data/delivery_h2.csv")
print(h1.shape, h2.shape)
h2.head(3)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
(816, 3) (760, 3)
order_id days rating
0 10817 4.0 3.0
1 10818 4.0 4.0
2 10819 2.0 3.0

concat: друг под другом

Функция pd.concat получает список таблиц и ставит их одну под другой:

[ ]816 + 760 = 1576 строк
both = pd.concat([h1, h2])
print(both.shape)
both.tail(3)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
(1576, 3)
order_id days rating
757 11574 3.0 4.0
758 11575 6.0 3.0
759 11576 5.0 NaN

Строк стало 1576 — но посмотрите на индекс: последняя метка 759, а не 1575. concat сохраняет метки каждой части. У обеих таблиц они шли с нуля, поэтому теперь метки повторяются:

[ ]Две строки с меткой 5
both.loc[5]
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
order_id days rating
5 10006 3.0 NaN
5 10822 2.0 3.0

loc[5] вернул две строки — по одной из каждого полугодия. Это почти никогда не то, что нужно. Параметр ignore_index=True нумерует строки заново. На двух маленьких таблицах:

[ ]Метки подряд: 0, 1, 2, 3
a = pd.DataFrame({"x": [1, 2]})
b = pd.DataFrame({"x": [3, 4]})
pd.concat([a, b], ignore_index=True)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
x
0 1
1 2
2 3
3 4
Вопрос

Те же таблицы a и b, но без ignore_index. Что выведет print(pd.concat([a, b]).index.tolist())?

[ ]Упражнение 1Доставка за год решено

Склейте h1 и h2 (в этом порядке) в таблицу year с индексом от нуля подряд. В n_orders сохраните число строк, в avg_rating — среднюю оценку за год.

year = ...
n_orders = ...
avg_rating = ...

Откуда строка

После склейки уже не видно, из какого файла пришла строка. Если это важно, источник записывают в столбец до склейки — например, методом assign, который возвращает таблицу с новым столбцом:

[ ]Пометить полугодие и склеить
marked = pd.concat([h1.assign(half=1), h2.assign(half=2)], ignore_index=True)
print(both.index.is_unique, marked.index.is_unique)
marked.groupby("half")["rating"].mean()
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
False True
half
1    3.691871
2    3.606061
Name: rating, dtype: float64

Первая строка вывода — проверка меток атрибутом индекса is_unique («уникален ли»): у склейки без ignore_index метки повторяются (False), у новой — нет (True).

Если столбцы разные

concat сопоставляет столбцы по названиям, а не по порядку. Если в одной из таблиц столбца нет, на его месте окажутся пропуски:

[ ]В феврале появился столбец tips
jan = pd.DataFrame({"city": ["Омск", "Тула"], "cups": [120, 95]})
feb = pd.DataFrame({"city": ["Омск", "Пермь"], "cups": [130, 60], "tips": [400, 150]})
pd.concat([jan, feb], ignore_index=True)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
city cups tips
0 Омск 120 NaN
1 Тула 95 NaN
2 Омск 130 400.0
3 Пермь 60 150.0

Это удобно — ничего не теряется. Но если столбец в двух файлах назван по-разному (cups и Cups), pandas посчитает их разными столбцами, и в обоих будет половина пропусков. После склейки стоит взглянуть на isna().sum().

[ ]Упражнение 2Полугодия решено

По таблице marked соберите by_half — таблицу по полугодиям (полугодие в индексе) со столбцами: orders — число заказов, days — средний срок доставки, no_rating — число заказов без оценки. В slower_half сохраните номер полугодия, в котором везли дольше. В by_half должно быть ровно три столбца.

by_half = ...
slower_half = ...

Много файлов

Когда файлов больше двух, таблицы собирают в список циклом — а потом склеивают один раз. Три метеостанции, три файла:

[ ]Прочитать три файла в список
parts = []
for name in ["center", "airport", "forest"]:
    part = pd.read_csv("data/station_" + name + ".csv")
    part["station"] = name
    parts.append(part)
print(len(parts), parts[0].shape)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
3 (28, 5)
[ ]Упражнение 3Три станции решено

В списке parts — три таблицы, в каждой есть столбец station. Склейте их в таблицу stations с индексом от нуля. В station_temp сохраните среднюю температуру (temp) по станциям, округлённую до двух знаков.

stations = ...
station_temp = ...

Склейка столбцами

С параметром axis=1 таблицы ставятся не друг под другом, а рядом:

[ ]Рядом — по меткам строк
left = pd.DataFrame({"city": ["Омск", "Тула"], "cups": [120, 95]})
right = pd.DataFrame({"manager": ["Анна", "Олег"]})
pd.concat([left, right], axis=1)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
city cups manager
0 Омск 120 Анна
1 Тула 95 Олег

Осторожно: строки сопоставляются не по порядку, а по меткам индекса. Возьмём из left только город, где продано больше ста чашек, и приставим к нему последнюю строку right:

[ ]По одной строке с каждой стороны — а в результате две
big = left[left["cups"] > 100]
print(big)
pd.concat([big, right.tail(1)], axis=1)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
   city  cups
0  Омск   120
city cups manager
0 Омск 120.0 NaN
1 NaN NaN Олег

В обеих таблицах по одной строке, но метки у них разные: 0 и 1. Поэтому строки не встали рядом: получились две строки, в каждой из которых половина ячеек — NaN. А если бы метки случайно совпали — например, обе таблицы прочитаны из разных файлов и пронумерованы с нуля, — в одну строку склеились бы данные, которые никак друг с другом не связаны.

Поэтому таблицы с общим признаком соединяют не через concat, а по ключу — методом merge. О нём следующий урок.

Итоги

  • pd.concat([a, b], ignore_index=True) — таблицы друг под другом, индекс заново.
  • Столбцы сопоставляются по названиям; чего нет — заполняется NaN.
  • Источник строки записывайте в столбец до склейки.
  • Много файлов: собрать список, склеить один раз.
  • axis=1 ставит таблицы рядом по меткам индекса; для соединения по смыслу нужен merge.

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

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