Индикатор объединения в Polars: Полное руководство
Узнайте, как добавлять индикаторные столбцы к операциям объединения в Polars для отслеживания совпавших и несовпавших строк, как в pandas и STATA. Полное руководство с примерами кода и решениями проблем.
Как получить аналогичный результат с помощью polars? При объединении двух таблиц в STATA выводится количество объединенных и не объединенных строк. Например, при использовании 1:1 объединения по столбцу ‘make’ между таблицами autosize и autoexpense, STATA показывает, сколько строк было сопоставлено из каждого набора данных. Я ищу способ отображения совпавших и несовпавших строк в операции объединения Polars, аналогично тому, как работает функция merge в pandas с параметром indicator.
Polars: Работа с индикаторами при объединении данных
В настоящее время Polars не имеет встроенной опции индикатора, подобной функции merge() в pandas, для автоматического отслеживания совпавших и несопоставленных строк. Однако существует несколько обходных путей, которые можно реализовать для достижения аналогичного функционала и отслеживания происхождения строк после операции объединения.
Содержание
- Текущее состояние поддержки индикаторов в Polars
- Обходной путь 1: Создание индикаторного столбца вручную
- Обходной путь 2: Пост-объединительный анализ
- Обходной путь 3: Пользовательская функция объединения
- Сравнение с Pandas и STATA
- Будущие разработки в Polars
Текущее состояние поддержки индикаторов в Polars
На текущую версию Polars не поддерживает нативно индикаторные столбцы в операциях объединения. Это была запрошенная функция, где пользователи хотели получить “индикатор, опцию validate в объединении dataframe” для проверки совпавших и несопоставленных строк после объединения.
В отличие от pandas, который предоставляет параметр indicator=True в merge(), метод join() Polars ориентирован на производительность и не автоматически отслеживает происхождение строк. В документации Polars упоминаются различные стратегии объединения, но не включена встроенная функциональность индикаторов.
Обходной путь 1: Создание индикаторного столбца вручную
Вы можете вручную создавать индикаторные столбцы, определяя, какие строки происходят из какого набора данных:
import polars as pl
# Пример данных
df1 = pl.DataFrame({
'make': ['Toyota', 'Honda', 'Ford'],
'size': ['medium', 'small', 'large']
})
df2 = pl.DataFrame({
'make': ['Toyota', 'Honda', 'BMW'],
'expense': [25000, 18000, 35000]
})
# Выполнение left join
result = df1.join(df2, on='make', how='left')
# Добавление индикаторного столбца вручную
result = result.with_columns(
pl.when(pl.col('expense').is_null())
.then('left_only')
.when(pl.col('make').is_in(df2['make']))
.then('both')
.otherwise('right_only')
.alias('merge_indicator')
)
print(result)
Этот подход создает индикаторный столбец, который показывает:
- ‘both’ для совпавших строк
- ‘left_only’ для строк только в левом dataframe
- ‘right_only’ для строк только в правом dataframe
Обходной путь 2: Пост-объединительный анализ
Другой подход - анализировать результат объединения для подсчета совпавших и несопоставленных строк:
def analyze_join_result(left_df, right_df, join_result, join_type='left'):
"""
Анализ результата объединения для отображения количества совпавших/несопоставленных строк
"""
# Подсчет уникальных значений в ключевом столбце для каждого dataframe
left_unique = left_df.select('make').n_unique()
right_unique = right_df.select('make').n_unique()
# Подсчет совпавших строк (не-null в столбцах правого dataframe)
if join_type in ['left', 'inner', 'full']:
matched_rows = join_result.filter(
~pl.col('expense').is_null()
).height
else:
matched_rows = 0
# Расчет несопоставленных строк на основе типа объединения
if join_type == 'left':
unmatched_left = left_unique - matched_rows
unmatched_right = 0
elif join_type == 'right':
unmatched_left = 0
unmatched_right = right_unique - matched_rows
elif join_type == 'full':
unmatched_left = left_unique - matched_rows
unmatched_right = right_unique - matched_rows
else: # inner
unmatched_left = left_unique - matched_rows
unmatched_right = right_unique - matched_rows
# Отображение результатов, аналогично выводу STATA
print(f"Тип объединения: {join_type.upper()}")
print(f"Строк из левого набора данных: {left_unique}")
print(f"Строк из правого набора данных: {right_unique}")
print(f"Совпавших строк: {matched_rows}")
print(f"Несопоставленных строк из левого: {unmatched_left}")
print(f"Несопоставленных строк из правого: {unmatched_right}")
print(f"Всего строк в результате: {join_result.height}")
# Использование
result = df1.join(df2, on='make', how='left')
analyze_join_result(df1, df2, result, 'left')
Обходной путь 3: Пользовательская функция объединения
Создайте комплексную функцию объединения, которая предоставляет подробный вывод, аналогичный STATA:
def smart_join(left_df, right_df, on=None, how='left', **kwargs):
"""
Расширенная функция объединения с отслеживанием строк и анализом
"""
# Выполнение объединения
result = left_df.join(right_df, on=on, how=how, **kwargs)
# Получение имен столбцов из правого dataframe (исключая ключи объединения)
right_cols = [col for col in right_df.columns if col not in (on if isinstance(on, list) else [on])]
# Создание индикаторного столбца
if how == 'left':
indicator = pl.when(pl.col(right_cols[0]).is_null()).then('left_only').otherwise('both')
elif how == 'right':
indicator = pl.when(pl.col(right_cols[0]).is_null()).then('right_only').otherwise('both')
elif how == 'full':
indicator = pl.when(
pl.col(right_cols[0]).is_null() & pl.col(on if isinstance(on, list) else [on]).is_not_null()
).then('left_only').when(
pl.col(right_cols[0]).is_not_null() & pl.col(on if isinstance(on, list) else [on]).is_null()
).then('right_only').otherwise('both')
else: # inner
indicator = pl.lit('both')
result = result.with_columns(indicator.alias('merge_indicator'))
# Выполнение анализа
left_count = left_df.height
right_count = right_df.height
matched_count = result.filter(pl.col('merge_indicator') == 'both').height
unmatched_left = result.filter(pl.col('merge_indicator') == 'left_only').height
unmatched_right = result.filter(pl.col('merge_indicator') == 'right_only').height
# Вывод анализа
print(f"\n{'='*50}")
print(f"АНАЛИЗ ОБЪЕДИНЕНИЯ - {how.upper()} JOIN")
print(f"{'='*50}")
print(f"Строк в левом наборе данных: {left_count}")
print(f"Строк в правом наборе данных: {right_count}")
print(f"Совпавших строк: {matched_count}")
print(f"Несопоставленных строк из левого: {unmatched_left}")
print(f"Несопоставленных строк из правого: {unmatched_right}")
print(f"Всего строк в результате: {result.height}")
print(f"{'='*50}\n")
return result
# Использование
result = smart_join(df1, df2, on='make', how='left')
Сравнение с Pandas и STATA
Объединение в Pandas с индикатором
# Подход с pandas
import pandas as pd
df1_pd = df1.to_pandas()
df2_pd = df2.to_pandas()
pandas_result = pd.merge(
df1_pd, df2_pd,
on='make',
how='left',
indicator=True
)
print(pandas_result['_merge'].value_counts())
Вывод объединения в STATA
STATA предоставляет подробный вывод, показывающий:
- Количество наблюдений из основного набора данных
- Количество наблюдений из используемого набора данных
- Количество совпадений
- Количество несопоставленных строк из каждого набора данных
Сравнение с Polars
Polars в настоящее время требует ручной реализации этой функциональности, но предлагает:
- Лучшую производительность для больших наборов данных
- Более гибкие операции объединения
- Лучшую эффективность использования памяти
- Более чистый API для сложных операций
Будущие разработки в Polars
Сообщество Polars признало необходимость функциональности индикаторов. Проблема на GitHub #5983 специально запрашивает:
“Индикатор полезен, когда нужно проверить совпавшие строки против несопоставленных после объединения”
Также есть проблема #2377, запрашивающая:
“Добавить необязательный валидационный вывод к объединениям”
Предлагаемая функция будет включать:
- Параметр
indicator=True, аналогичный pandas - Опцию
validateдля валидации типа объединения - Автоматическое отслеживание происхождения строк
Это указывает на то, что будущие версии Polars могут включить нативную поддержку индикаторных столбцов, что сделает обходные пути ненужными.
Источники
- GitHub Issue #5983: Add indicator, validate option in dataframe join
- Stack Overflow: Show matched rows in polars join
- Polars User Guide: Joins
- Polars Documentation: DataFrame.join
- Stack Overflow: Get indicator column when using df.join
- GitHub Issue #2377: Add optional validation output to joins
Заключение
Хотя Polars в настоящее время не имеет встроенной функциональности индикаторов, как в pandas или STATA, вы можете достичь аналогичных результатов через несколько обходных путей:
- Ручные индикаторные столбцы - Создайте собственную логику индикатора с помощью условных выражений Polars
- Пост-объединительный анализ - Подсчитывайте совпавшие и несопоставленные строки после выполнения объединения
- Пользовательская функция объединения - Постройте комплексное решение, предоставляющее подробный анализ совпавших и несопоставленных строк
Для немедленных потребностей подход с пользовательской функцией объединения обеспечивает наиболее похожий на STATA опыт с подробным выводом о совпавших и несопоставленных строках. Однако следите за развитием Polars, так как нативная поддержка индикаторов может быть реализована в будущих версиях, что сделает эти обходные пути устаревшими.
Компромисс заключается в том, что Polars отдает приоритет производительности и гибкости вместо удобных функций, но для большинства случаев использования обходные пути достаточны и сохраняют отличные характеристики производительности Polars.