← Все курсы · Курс Python · Все руководства

pandas.merge: левое соединение, внутреннее соединение и то, которое удвоило доход

Четыре способа, одно количество строк и проверка, которая должна следовать за каждым слиянием. · Часть Analyst Prep Kit

К , аналитик данных · Опубликовано

К концу этой страницы вы сможете прикрепить столбцы из одного DataFrame к другому по общему ключу, выберите правильный how для вопроса сразу посмотрите, какие строки не совпадают, и уловите ошибку, которая незаметно увеличивает каждую сумму в кадре. Это около двадцати пяти минут, и все приведенные ниже выходные данные были получены путем запуска кода.

Вот что делать сегодня при каждом написанном вами слиянии. Выведите количество строк непосредственно перед и сразу после него. Левое слияние не должно изменять количество строк, а если это произошло, то правая таблица имеет ключ более одного раза, и ваши итоговые значения только что увеличились.

Краткая версия: merge объединяет строки из двух кадров, где их ключи совпадают, и количество получаемых строк зависит от того, сколько раз каждый ключ появляется на каждой стороне.

Одна клавиша дважды справа — это идея, поэтому она получает картину.

One key twice on the right becomes two rows out On the left a single row is drawn as a wide box, holding the key Desk and the value 880. To its right stands a small lookup table with two rows, and both of those rows carry the same key, Desk. Two lines run from the single left-hand row, one to each of the two matching lookup rows, so the one row is paired twice. On the far right the result is drawn as two separate output rows, and both of them contain Desk and 880; the value 880 is ringed in amber in each of them to show that it is the same original figure appearing twice. One row went in and two came out, without anything being added to the left-hand table. Desk 880 DeskDesk DeskDesk 880880
Поступает один заказ. В таблице поиска есть ключ дважды, поэтому заказ дважды спаривается и дважды выходит, оба раза перенося один и тот же код 880. К данным ничего не было добавлено; общая сумма только что выросла.
Что вы узнаете
  1. объединить в одну строку
  2. Четыре «как» и строки, которые они дают
  3. показатель: с какой стороны пришел этот ряд
  4. Умножение
  5. проверить: запретить слияние
  6. Имена столбцов, которые конфликтуют
  7. Ключи с разными именами и разными типами
  8. объединить, объединить и объединить
  9. Полное до и после
  10. Пограничные случаи, нарушающие слияние
  11. Почему это работает
  12. Использование этого в вашем собственном проекте
  13. Все на одном экране
Каждый вывод на этой странице реален. Шестнадцать заказов на общую сумму 9890 и таблица продуктов из трех строк — те же таблицы, которые используются во всем этом наборе руководств, — объединены в pandas 3.0.2 с скопированными обратно результатами. Если ты знаешь SQL-СОЕДИНЕНИЯ, это одна и та же операция с разными словами, и два режима отказа идентичны.

1. объединить в одну строку

Два кадра, один общий столбец, один вызов.

orders.merge(products, on="product", how="left")

   order_id product   category  cost
0      1001    Desk  Furniture   140
1      1002   Chair  Furniture    52
2      1003    Desk  Furniture   140
3      1004    Lamp   Lighting    22

shape (16, 11)   revenue 9890

Шестнадцать строк на входе, шестнадцать строк на выходе, а доход не изменился и составил 9890. Две колонны прибыли, category и cost, прикрепляется к каждому заказу путем сопоставления названия продукта.

Прочтите аргументы как предложение: принимайте заказы, привозите продукцию, сопоставляйте. productи сохраняйте каждый порядок, независимо от того, совпадает он или нет. Эта последняя часть how, и именно аргумент решает всё.

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

2. Четыре «как» и ряды, которые они дают

Перед пояснением: в таблице товаров отсутствуют лампы, а четыре из шестнадцати заказов — лампы. Предскажите количество строк для каждого из четырех способов.

how=left    rows= 16   revenue=9890   missing cost=4
how=inner   rows= 12   revenue=8290   missing cost=0
how=right   rows= 12   revenue=8290   missing cost=0
how=outer   rows= 16   revenue=9890   missing cost=4

Четыре разных ответа на один и тот же вопрос, и разница между первыми двумя составляет 1600 доходов, то есть от лампового бизнеса.

КакдержитИспользуйте его, когда
leftКаждая строка левого кадра, совпадающая или нетПочти всегда. Левый кадр — это ваши данные, и вы их украшаете.
innerТолько строки, совпадающие с обеих сторонВы искренне хотите перекрёсток и проверили, что он выпадет.
rightКаждая строка правого кадраРедко. Поменяйте местами рамки и вместо этого используйте левую; оно читается лучше.
outerВсё с обеих сторонСогласование двух списков и необходимость посмотреть, что находится только на каждой стороне.

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

Правило: если количество строк уменьшилось, внутреннее соединение что-то выбросило, и вы должны знать, что именно.

3. показатель: с какой стороны пришел этот ряд

Один аргумент превращает «некоторые строки не совпали» в число, которое вы можете прочитать.

orders.merge(products_missing_lamp, on="product", how="outer", indicator=True)

_merge
both          12
left_only      4
right_only     0

Двенадцать совпали, в четырех заказах не было обнаружено ни одного товара, и ни один товар не остался неиспользованным. Эти три числа представляют собой форму соединения, и для их получения требуется одно ключевое слово.

Используйте его при разработке каждого слияния, а затем удалите его или сохраните столбец и отфильтруйте его. Таким образом вы получите сами несовпадающие строки, а не только их количество:

m = left.merge(right, on=key, how="outer", indicator=True)
m[m["_merge"] == "left_only"]     # the rows that found no partner

right_only на ненулевое значение тоже стоит обратить внимание. Это означает, что в таблице поиска есть записи, которые никто не использует, что обычно безвредно и иногда сообщает вам, что ключ неправильный: поиск, в котором вообще ничего не совпадает, возвращается в виде каждой строки с одной стороны и каждой строки с другой.

4. Умножение

Перед пояснением: в таблице продуктов появится вторая строка для «Стол», идентичная первой. Теперь у него четыре ряда вместо трех. Предскажите, что вернет слияние.

rows    16  ->  23
revenue 9890 -> 14950
desk rows  7 ->  14

Семь дополнительных строк и 5060 дополнительных доходов от добавления одной строки в таблицу поиска. К заказам ничего не добавлялось и ни один заказ не менялся.

Механизм именно такой, как на картинке вверху. Семь орденов — столы; каждый из них теперь соответствует двум строкам в таблице продуктов; поэтому каждый выходит дважды. Семь заказов превратились в четырнадцать рядов, и доход от каждого заказа на столе учитывается дважды, то есть 5060 учитываются во второй раз.

Самое опасное на странице то, что не происходит. Никаких ошибок и предупреждений нет. Фрейм выглядит совершенно нормально, каждое отдельное значение в нем правильное, а любое общее значение, вычисленное впоследствии, неверно, и это незаметно, если вы не знали заранее количество строк.

Это также совершенно обычно в реальных данных. Таблица продуктов с одной строкой для каждого продукта и одной строкой для каждого изменения цены. Таблица клиентов со строкой на адрес. Поиск, который был добавлен дважды. Каждая из них представляет собой разумную таблицу, в которой нет одной строки на ключ, и слияние с ней умножается.

Произнесите вслух, что бы вы увидели, если бы это произошло при слиянии внутри конвейера, который вы не писали. Цифра дохода слишком завышена, нигде нет ошибок, и каждая строка, которую вы проверяете, верна.

5. Подтвердите: откажитесь от слияния

pandas проверит мощность за вас и увеличит, а не умножит.

orders.merge(products, on="product", how="left", validate="m:1")
# clean table: accepted

orders.merge(products_with_duplicate_desk, on="product", how="left", validate="m:1")
# MergeError: Merge keys are not unique in right dataset; not a many-to-one merge

Это единственный наиболее ценный аргумент во всей этой функции, и его почти никто не использует. validate="m:1" говорит: многие строки слева могут совпадать, но каждый ключ должен появляться не более одного раза справа. Это предположение, которое вы уже делаете каждый раз, когда прикрепляете поиск, записанное, чтобы компьютер мог его реализовать.

подтвердитьОзначает
"m:1"От многих левых рядов к одному правому ряду. Прикрепляю поиск. Обычный случай.
"1:1"Обе стороны уникальны. Объединение двух версий одной и той же записи.
"1:m"От одного левого ряда до множества правых рядов. Расширение родителя на его дочерние элементы.
"m:m"Никаких ограничений. Это поведение по умолчанию, и оно увеличивается.

Добавляйте его к каждому написанному вами слиянию. Оно стоит девять символов, превращает невидимую инфляцию в исключение в тот момент, когда оно происходит, и исключение называет сторону, которая неправа.

6. Конфликтующие имена столбцов

Если в обоих фреймах есть столбец с одинаковым именем, и он не является ключом, pandas сохраняет оба и переименовывает их.

['units_x', 'units_y']

_x это левый кадр и _y это правильно. Это разумное значение по умолчанию, и ужасно обнаружить в сценарии шесть месяцев спустя, потому что ничего о units_x говорит, из какого стола оно взято.

Два лучших варианта. Установите свои собственные суффиксы при слиянии, которое занимает две секунды и впоследствии читается правильно:

orders.merge(products, on="product", suffixes=("_order", "_catalogue"))

Или, что еще лучше, удалите или переименуйте ненужные столбцы перед объединением, чтобы никогда не возникало коллизий. Слияние, которое добавляет три нужных вам столбца, гораздо легче читать, чем слияние, которое включает пятнадцать и переименовывает четыре из них.

7. Ключи с разными именами и разными типами.

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

orders.merge(catalogue, left_on="product", right_on="item", how="left")

rows 16, and the result keeps both key columns: ['product', 'item']

Обратите внимание на вторую половину. Оба ключевых столбца сохраняются в результате, сохраняя одинаковые значения, поэтому в кадре имеется избыточный столбец. Немедленно отбросьте это, иначе следующий человек будет задаваться вопросом, кто из них авторитетнее.

Типы более строгие, и pandas здесь ведет себя лучше, чем большинство инструментов. Слияние текстового ключа с целочисленным ключом ничего не означает молча; это повышает:

ValueError: You are trying to merge on string and int64 columns for key 'order_id'.

Это действительно хорошая новость, потому что та же ошибка при поиске в электронной таблице приводит к #N/A в некоторых строках и в SQL выдает нулевые совпадения, и оба эти явления выглядят скорее как проблема с данными, чем как проблема с типом. Вот это тебя останавливает. Исправьте типы, обычно делая обе стороны текстовыми, если ключ является идентификатором, который является аргументом в как загружается CSV.

Что такое нет поймана разница в самих значениях: конечный пробел, другой регистр, код с ведущим нулем только с одной стороны. Они сливаются без ошибок и ничему не соответствуют, а признаком этого является подозрительно круглое количество несовпадающих строк в таблице. indicator столбец.

8. объединить, объединить и объединить

Три функции, которые люди путают на разных работах.

merge совпадения по столбцам. Это то, что хочется почти всегда, и все выше об этом.

join это удобный метод, который соответствует индекс по умолчанию. Он короче, когда ваши кадры действительно проиндексированы по ключу, и является источником путаницы, когда это не так, потому что он молча использует индекс, о котором вы забыли. Если есть сомнения, используйте merge и назовите столбцы.

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

pd.concat([jan, feb, mar], ignore_index=True)      # rows must add up
orders.merge(products, on="product", how="left")   # rows must not change

Представьте себе конвейер, который вы поддерживаете. Сколько в нем слияний и для скольких из них вы знаете ожидаемое количество строк?

Полное до и после

Та же работа: привязать стоимость продукции к шестнадцати заказам.

До

df = orders.merge(products, on="product")

# no how, so it defaults to inner
# no validate, so a duplicate key would multiply
# no row count check, so neither would be noticed

Три варианта по умолчанию приняты без принятия решения. Если при поиске когда-либо теряется продукт, строки исчезают. Если когда-либо появится дубликат, строки умножатся. Оба меняют итоги и ни один ничего не говорит.

после

before = len(orders)                       # 16

df = orders.merge(
    products[["product", "category", "cost"]],   # only what is needed
    on="product",
    how="left",                                  # never lose a row of my data
    validate="m:1",                              # and refuse if the lookup repeats
    indicator=True,
)

assert len(df) == before, f"merge changed the row count: {before} -> {len(df)}"
print(df["_merge"].value_counts())          # both 16, left_only 0
print(df["cost"].isna().sum())              # 0 unmatched

Подсчет строк подтвержден, кардинальность обеспечивается pandas, а не надеждой, несовпадающие строки подсчитываются, а не предполагаются, и передаются только три нужных столбца.

Претензия и вот почему validate принадлежит при каждом слиянии: добавление одной повторяющейся строки в справочную таблицу из трех строк привело к увеличению числа строк с 16 строк и 9890 до 23 строк и 14 950, и при этом не возникло ни ошибок, ни предупреждений, ни неправильных отдельных значений где-либо в кадре.

Пограничные случаи, нарушающие слияние

Шесть, которые стоит знать.

Нули в ключе. По умолчанию pandas сопоставляет нуль с нулем, поэтому каждая строка с отсутствующим ключом слева соединяется с каждой строкой с отсутствующим ключом справа, что представляет собой умножение, ожидающее своего выполнения. Удалите или заполните их перед объединением.

Пробелы и регистр в ключе. Сливается без ошибок, ничего не соответствует и отображается только в indicator имеет значение. Сначала очистите ключевые столбцы, как и при любом другом объединении.

Индекс после слияния. merge отбрасывает индекс левого кадра и дает вам новый, поэтому все, что зависит от старого индекса, спокойно ломается. Сбросьте или повторно подключите специально.

Слияние в цикле. Многократное объединение одного кадра в растущий результат происходит медленно и увеличивает риск того, что умножение произойдет один раз и останется незамеченным. Создайте список и объедините его один раз или сократите список, каждый раз проверяя счетчик.

Память. При слиянии создается новый фрейм со столбцами обоих, поэтому объединение двух широких таблиц может в несколько раз превышать размер каждой из них. Выберите нужные вам столбцы справа до объединения, а не после.

Многие ко многим намеренно. Иногда это действительно правильно, например, разложить заказ на строки. Тогда скажи это с validate="1:m" и сверить количество строк с ожидаемым расширением, чтобы запланированное умножение было задокументировано, а непреднамеренное все равно не удалось.

Почему это работает

Умножение — это не причуда pandas, это то, что означает сопоставление. Соединение соединяет каждую строку на одной стороне с каждой строкой на другой, ключ которой согласуется, поэтому размер вывода определяется тем, сколько раз каждый ключ встречается на каждой стороне, а не количеством строк в каждой таблице. В реляционной модели ключ — это именно столбец или набор столбцов, значение которых однозначно идентифицирует строку, и соединение с чем-то, что не является ключом, лишает этой гарантии (Кодд, 1970, Коммуникации ACM, 13(6), 377–387). «Один дубликат в таблице поиска» — это еще один способ сказать, что объединяемый столбец не является ключевым на этой стороне, и как только вы скажете это таким образом, семь дополнительных строк перестанут удивлять.

pandas намеренно отражает этот словарь, а не изобретает свой собственный, поэтому how берет те же четыре слова, которые использует база данных, и объясняет, почему поведение совпадает: библиотека была создана для выполнения операций реляционного стиля с табличными данными в памяти в Python, чтобы люди могли выполнять соединения и изменения, которые они уже делали в SQL, без перемещения данных (МакКинни, 2010, Материалы 9-й конференции «Питон в науке», 51–56). Это полезная часть для аналитика: то, что вы узнаете здесь, напрямую переносится на объединяется в SQL, включая два способа, которыми они идут не так.

Одно примечание к вопросам, заданным перед каждым ответом на этой странице. Побуждение себя сделать прогноз до того, как прочитать результат, — это один из немногих шагов обучения, который надежно улучшает то, что вы извлекаете, и это работает, даже если прогноз неверен (Фиорелла & Майер, 2016, Обзор педагогической психологии, 28(4), 717–741). 23 палочки, потому что вас попросили угадать 16.

Использование этого в вашем собственном проекте

Аудит каждого слияния в базе кода — это проект. Вместо этого сделайте это по порядку.

  1. Найдите слияния без how. По умолчанию это внутренние соединения, и их авторы обычно имели в виду левые.
  2. добавлять validate="m:1" для каждого слияния поиска. Девять символов, и умножение становится исключением.
  3. Утвердить количество строк вокруг любого левого слияния. Одна строчка, и она громко проваливается в момент ошибки.
  4. Использовать indicator=True развивая и прочтите три пункта, прежде чем удалять его.
  5. Перед объединением выберите правые столбцы, поэтому коллизии и память перестают быть проблемами.
  6. Сначала очистите ключевые столбцы, например, пробелы и тип, поскольку ни один из них не приводит к ошибке.

Если у вас под рукой есть бумага, один дополнительный эскиз стоит пяти минут. Запишите две таблицы в виде двух полей и рядом с каждой напишите, сколько раз в ней может появляться одно и то же значение ключа: один раз или несколько раз. Эти два ответа и есть validate строка, и большинство людей обнаруживают, что их запись приводит к появлению таблицы, которая, как они предполагали, содержала одну строку на ключ, но это не так.

Подробнее об этом и еще что-нибудь подобное. Все инструкции находятся в одном месте на индекс направляющих. Шагом после присоединения обычно является подведение итогов, то есть pandas.groupby.

Все на одном экране

Это лист поиска. Закройте правую колонку, проработайте левую и произнесите каждый ответ вслух, прежде чем проверять его.

вещьЧто он делает
merge(on=, how=)Пары строк, где совпадают ключи.
ЧекКоличество строк и одна сумма до и после.
how="left"Сохраняет каждую левую строку. Выбор по умолчанию.
how="inner"Только совпадающие строки. Удаляет молча.
how="outer"Всё с обеих сторон. Для примирения.
Количество строк уменьшилосьВнутреннее соединение удаляет строки. Узнайте какой.
Количество строк увеличилосьПравый ключ не уникален. Итоговые суммы теперь завышены.
indicator=TrueДобавляет _merge: оба, только слева, только справа.
validate="m:1"Повышается, если правая клавиша повторяется. Используйте его каждый раз.
Другие значения проверки1:1, 1:m, и m:m что является незащищенным значением по умолчанию.
Столкновение имен столбцовСтановиться _x и _y. Набор suffixes или сначала бросьте их.
Различные названия клавишleft_on и right_on. Обе колонны сохранились; бросьте один.
Различные типы ключейВызывает Ошибка значения. Это лучше, чем ничего не соответствовать.
Различные ключевые значенияРегистр, пробелы, ведущие нули. Ни ошибок, ни совпадений.
Нули в ключеСоответствуйте друг другу, что умножается. Сначала удалите их.
joinПо умолчанию соответствует индексу. Предпочитайте объединить и назвать столбцы.
concatСтеки, а не совпадения. Количество строк должно суммироваться.
Единственная привычка, которую следует сохранить. Помещать validate= при каждом слиянии. Это единственное, что на этой странице превращает молчаливый провал в громкий в тот момент, когда он происходит, и его написание заставляет вас заявить, что вы думаете о двух таблицах, и именно в этом обычно и заключается ошибка. Если слияние ведет себя не так, как описано на этой странице, существует общая ошибка. шлейф диагностики на предмет застревания.

Еще одна мысль, и мне бы искренне хотелось услышать ответы других людей. В моей таблице цен во время исправления данных появилась одна повторяющаяся строка, поэтому месячный доход за два месяца оказался выше восьми процентов, и каждая проверяемая строка была верной. Что для вас незаметно умножило объединение?

Ссылки

Слияние прошло успешно, и количество строк увеличилось, что означает, что что-то совпало дважды.

Python для аналитиков составляет 203 страницы, каждый тип соединения читается построчно, с указанием количества строк до и после.

Python для аналитиков, 19 $ →
Практикуйте слияния, которые намеренно идут не так.

тот Курс Python дает вам повторы: поиск повторяющихся ключей, отсутствующих ключей и несовпадающих типов, а также флеш-карточки, на которых how сохраняет список строк и проводит пробный экзамен, который запрашивает количество строк перед запуском слияния. Теперь вы владеете методом; комплект - это практика. Ничего устанавливать, учетная запись не требуется.

Откройте комплект Python →