Материал рассматривает методы работы с повторяющимися строками или значениями столбцов в DataFrame
. В частности рассматриваются методы:
DataFrame.duplicated()
возвращает логическую индексацию дубликатов в DataFrame
;Series.duplicated()
возвращает логическую индексацию дубликатов в Series
;DataFrame.drop_duplicates()
удаляет дубликаты в DataFrame
;Series.drop_duplicates()
удаляет дубликаты в Series
;DataFrame.duplicated(subset=None, keep='first')
:Метод DataFrame.duplicated()
возвращает логическую Series
, которая обозначает повторяющиеся строки.
Учет определенных столбцов subset
при поиске дубликатов не является обязательным.
Принимаемые аргументы:
subset=None
- поиск дубликатов только в определенных столбцах. По умолчанию используются все столбцы. Принимает метку столбца или список меток столбцов.keep='first'
- определяет, какие дубликаты (если есть) оставлять в DataFrame
.first
: пометить дубликаты как True
, за исключением первого вхождения.last
: пометить дубликаты как True
, за исключением последнего вхождения.False
: пометить все дубликаты как True
. DataFrame.duplicated()
Рассмотрим следующий набор данных:
>>> import pandas as pd df = pd.DataFrame({ 'brand': ['Yum Yum', 'Yum Yum', 'Indomie', 'Indomie', 'Indomie'], 'style': ['cup', 'cup', 'cup', 'pack', 'pack'], 'rating': [4, 4, 3.5, 15, 5] }) >>> df # brand style rating # 0 Yum Yum cup 4.0 # 1 Yum Yum cup 4.0 # 2 Indomie cup 3.5 # 3 Indomie pack 15.0 # 4 Indomie pack 5.0
По умолчанию для каждого набора повторяющихся значений первое вхождение имеет значение False
, а все остальные - True
.
>>> df.duplicated() # 0 False # 1 True # 2 False # 3 False # 4 False # dtype: bool
А как собственно посмотреть убранные дубликаты из DataFrame
? Просто используем логическую индексацию:
>>> df.loc[df.duplicated(), :] # brand style rating # 1 Yum Yum cup 4.0
Теперь, что бы посмотреть DataFrame
без дубликатов, необходимо в исходный DataFrame
передать отрицание ~df.duplicated()
или использовать метод DataFrame.drop_duplicates()
:
# передадим в `DataFrame` отрицание # логической индексации >>> df.loc[~df.duplicated(), :] # brand style rating # 0 Yum Yum cup 4.0 # 2 Indomie cup 3.5 # 3 Indomie pack 15.0 # 4 Indomie pack 5.0
При использовании keep='last'
, для последнего вхождения каждого набора повторяющихся значений устанавливается значение False
, а для всех остальных - значение True
.
>>> df.duplicated(keep='last') # 0 True # 1 False # 2 False # 3 False # 4 False # dtype: bool
Если установить для keep=False
, то все дубликаты будут иметь значение True
.
>>> df.duplicated(keep=False) # 0 True # 1 True # 2 False # 3 False # 4 False # dtype: bool
Чтобы найти дубликаты в определенных столбцах, необходимо использовать аргумент subset
.
>>> df.duplicated(subset=['brand']) # 0 False # 1 True # 2 False # 3 True # 4 True # dtype: bool
Series.duplicated(keep='first')
:Метод Series.duplicated()
возвращает логическую Series
, которая обозначает повторяющиеся строки.
Повторяющиеся значения в результирующей серии обозначаются как True
. Могут быть указаны либо все дубликаты, либо все, кроме первого, либо все дубликаты, кроме последнего.
Принимаемые аргументы:
keep='first'
- определяет, какие дубликаты (если есть) оставлять в DataFrame
.first
: пометить дубликаты как True
, за исключением первого вхождения.last
: пометить дубликаты как True
, за исключением последнего вхождения.False
: пометить все дубликаты как True
. Series.duplicated()
>>> import pandas as pd >>> animals = pd.Series(['llama', 'cow', 'llama', 'beetle', 'llama']) >>> animals.duplicated() # 0 False # 1 False # 2 True # 3 False # 4 True # dtype: bool # что эквивалентно: >>> animals.duplicated(keep='first')
Теперь смотрим убранные дубликаты из Series
, для этого просто используем логическую индексацию:
>>> animals.loc[animals.duplicated()] # 2 llama # 4 llama # dtype: object
А теперь чистый Series
- БЕЗ дубликатов, передав в исходный Series
отрицание логической индексации или можно использовать метод Series.drop_duplicates()
:
>>> animals.loc[~animals.duplicated()] # 0 llama # 1 cow # 3 beetle # dtype: object
При использовании keep='last'
последнее вхождение каждого набора повторяющихся значений устанавливается в False
, а все остальные - в True
:
>>> animals.duplicated(keep='last') # 0 True # 1 False # 2 True # 3 False # 4 False # dtype: bool
При установке keep=False
, все дубликаты имеют значение True
:
>>> animals.duplicated(keep=False) # 0 True # 1 False # 2 True # 3 False # 4 True # dtype: bool
DataFrame.drop_duplicates(subset=None, *, keep='first', inplace=False, ignore_index=False)
:Метод DataFrame.drop_duplicates()
возвращает DataFrame
с удаленными дубликатами строк.
Поиск дублирующих значений в определенных столбцах subset
не является обязательным. Индексы, в том числе индексы времени, игнорируются.
Принимаемые аргументы:
subset=None
- поиск дубликатов только в определенных столбцах. По умолчанию используются все столбцы. Принимает метку столбца или список меток столбцов.keep='first'
- определяет, какие дубликаты (если есть) оставлять в DataFrame
.first
: пометить дубликаты как True
, за исключением первого вхождения.last
: пометить дубликаты как True
, за исключением последнего вхождения.False
: пометить все дубликаты как True
. inplace=False
- следует ли изменять исходный DataFrame
, а не создавать новый.ignore_index=False
- если значение True
, то результирующая ось будет помечена как 0, 1, ..., n - 1
.DataFrame.drop_duplicates()
Рассмотрим следующий набор данных:
>>> import pandas as pd df = pd.DataFrame({ 'brand': ['Yum Yum', 'Yum Yum', 'Indomie', 'Indomie', 'Indomie'], 'style': ['cup', 'cup', 'cup', 'pack', 'pack'], 'rating': [4, 4, 3.5, 15, 5] }) >>> df # brand style rating # 0 Yum Yum cup 4.0 # 1 Yum Yum cup 4.0 # 2 Indomie cup 3.5 # 3 Indomie pack 15.0 # 4 Indomie pack 5.0
По умолчанию, метод удаляет повторяющиеся строки на основе всех столбцов.
>>> df.drop_duplicates() # brand style rating # 0 Yum Yum cup 4.0 # 2 Indomie cup 3.5 # 3 Indomie pack 15.0 # 4 Indomie pack 5.0
Чтобы удалить дубликаты в определенных столбцах, используем аргумент subset
.
>>> df.drop_duplicates(subset=['brand']) # brand style rating # 0 Yum Yum cup 4.0 # 2 Indomie cup 3.5
Чтобы удалить дубликаты значений столбцов 'brand'
и 'style'
и при этом сохранить последние вхождения, используем аргумент keep
.
>>> df.drop_duplicates(subset=['brand', 'style'], keep='last') # brand style rating # 1 Yum Yum cup 4.0 # 2 Indomie cup 3.5 # 4 Indomie pack 5.0
Series.drop_duplicates(*, keep='first', inplace=False, ignore_index=False)
:Метод Series.drop_duplicates()
возвращает Series
с удаленными дубликатами строк.
Принимаемые аргументы:
keep='first'
- определяет, какие дубликаты (если есть) оставлять в DataFrame
.first
: пометить дубликаты как True
, за исключением первого вхождения.last
: пометить дубликаты как True
, за исключением последнего вхождения.False
: пометить все дубликаты как True
. inplace=False
- следует ли изменять исходный DataFrame
, а не создавать новый.ignore_index=False
- если значение True
, то результирующая ось будет помечена как 0, 1, ..., n - 1
.Series.drop_duplicates()
Создадим серию с повторяющимися записями.
>>> import pandas as pd >>> import numpy as np >>> s = pd.Series(['llama', 'cow', 'llama', 'beetle', 'llama', 'hippo'], name='animal') >>> s # 0 llama # 1 cow # 2 llama # 3 beetle # 4 llama # 5 hippo # Name: animal, dtype: object
С помощью аргумента keep
можно изменить поведение выбора повторяющихся значений. Значение 'first'
сохраняет первое вхождение для каждого набора повторяющихся записей. Значение keep
по умолчанию 'first'
.
>>> s.drop_duplicates() # 0 llama # 1 cow # 3 beetle # 5 hippo # Name: animal, dtype: object
Значение keep='last'
сохраняет последнее вхождение для каждого набора повторяющихся записей.
>>> s.drop_duplicates(keep='last') # 1 cow # 3 beetle # 4 llama # 5 hippo # Name: animal, dtype: object
Значение keep=False
отбрасывает все наборы повторяющихся записей.
>>> s.drop_duplicates(keep=False) # 1 cow # 3 beetle # 5 hippo # Name: animal, dtype: object
Объекты pandas.Index
не обязательно должны быть уникальными и в нем могут встречаться повторяющиеся метки строк или столбцов. Поначалу это может сбить с толку. Например, в SQL метки строк аналогичны первичному ключу таблицы. Но одна из ролей библиотеки pandas
- очищать беспорядочные реальные данные, прежде чем они попадут в какую-либо систему. А реальные данные имеют дубликаты даже в полях, которые должны быть уникальными.
Некоторые методы pandas
(например, Series.reindex()
) просто не работают при наличии дубликатов. Выход не может быть определен, поэтому pandas
будет поднимать исключение.
>>> s1 = pd.Series([0, 1, 2], index=["a", "b", "b"]) >>> s1.reindex(["a", "b", "c"]) # Traceback (most recent call last): # ... # ... # ValueError: cannot reindex on an axis with duplicate labels
Можно проверить, является ли индекс (хранящий метки строк или столбцов) уникальным с помощью Index.is_unique
:
>>> df = pd.DataFrame({"A": [0, 1, 2]}, index=["a", "a", "b"]) >>> df # A # a 0 # a 1 # b 2 >>> df.index.is_unique # False >>> df.columns.is_unique # True
Примечание. Проверка уникальности индекса является несколько дорогостоящей для больших наборов данных. pandas кэширует этот результат, поэтому повторная проверка по тому же индексу происходит очень быстро.
Метод Index.duplicated()
вернет логический массив, указывающий, повторяется ли метка. Его можно использовать в логической индексации:
>>> df.loc[~df.index.duplicated(), :] # A # a 0 # b 2
Если необходима дополнительная логика для обработки повторяющихся меток, а не просто отбрасывание повторов, использование DataFrame.groupby()
для индекса является обычным приемом. Например, устраним дубликаты, взяв среднее значение всех строк с одинаковой меткой.
>>> df.groupby(level=0).mean() # A # a 0.5 # b 2.0
При обработке необработанных, беспорядочных данных можно сначала прочитать беспорядочные данные (которые потенциально могут иметь повторяющиеся метки), выполнить дедупликацию, а затем запретить дублирование в дальнейшем, чтобы гарантировать, что конвейер данных не будет создавать дубликаты.
# Внимание! Абстрактный код. raw_data = pd.read_csv("...") # удаляем дубликаты deduplicated = raw_data.groupby(level=0).first() # запретить повторяющиеся индексные метки deduplicated.flags.allows_duplicate_labels = False
Установка allows_duplicate_labels=False
для Series
или DataFrame
с повторяющимися метками или выполнение операции, которая вводит повторяющиеся метки в Series
/DataFrame
, вызовет исключение errors.DuplicateLabelError
.