Set Operations: Intersect & Except

Python · Combining DataFrames (SQL Joins & Unions)

Theory

SQL's INTERSECT returns rows present in both tables and EXCEPT (MINUS) returns rows in the first table but not the second, both without duplicates. In pandas, intersection of whole rows is a merge on all shared columns: a.merge(b, how='inner').drop_duplicates(). With identical column names, merge uses every common column as the key, so only rows equal in every column survive.

EXCEPT is an anti-join on all columns: m = a.merge(b.drop_duplicates(), how='left', indicator=True), then keep m['_merge'] == 'left_only' and drop the _merge column. For single values, Python sets or Index methods are simplest: pd.Index(a_ids).intersection(b_ids), .difference(b_ids), .union(b_ids) and .symmetric_difference(b_ids). The same ideas compare two snapshots of a table: rows in today but not yesterday are new, rows in yesterday but not today were removed.

Why we use it

Comparing two versions or two systems is a constant task - reconciling a source with a target, finding new or deleted records between snapshots, checking that two lists agree. Set operations answer these directly.

When to use it

Use merge-based intersect/except when comparing whole rows of two DataFrames with the same columns. Use Index or set operations when comparing just keys. Check that dtypes match first, or equal-looking values will not match.

How it works

  1. Compare table A with table B
  2. Comparing whole rows? Yes: Merge on all common columns. No: Keys only: pd.Index methods.
  3. Rows in both (INTERSECT)? Yes: Inner merge + drop_duplicates(). No: Left merge, indicator=True.
  4. For EXCEPT keep rows where _merge == 'left_only'
  5. Matching or differing rows

Syntax

intersect: a.merge(b, how='inner').drop_duplicates()
except: m = a.merge(b.drop_duplicates(), how='left', indicator=True)
        m[m['_merge'] == 'left_only'].drop(columns='_merge')
keys: pd.Index(x).intersection(y) / .difference(y)

Example

both = today.merge(yesterday, how='inner')
new_rows = (today.merge(yesterday, how='left', indicator=True)
              .query("_merge == 'left_only'").drop(columns='_merge'))

Key points

Python topics

Getting Started

Variables & Data Types

Operators

Strings

Lists

Tuples

Sets

Dictionaries

Control Flow

Loops

Functions & OOP

Working with Data

Tooling & Errors

File Handling

Exception Handling

NumPy Library

Pandas Basics

Data Cleaning

Combining DataFrames (SQL Joins & Unions)

GroupBy & SQL-Style Analytics

Reshaping & Workflow

Data Visualization

Machine Learning (Scikit-Learn)

Advanced Python & AI

T
Tech Town
Log InSign Up Free
Home SQL Python DSA Power BI Snowflake Databricks Spark Gen AI Practice Problems Contest Blog

Python for Data Analysts

From basics to business insights — the complete step-by-step Python roadmap. Click any topic in the sidebar to open it right here.

{{ sectionCount }}
Sections
{{ topicCount }}
Topics
Free
Forever
Hands-on practice Practice Python Online 141 Python questions for data analysts — strings, records, dates, statistics and regex — with hidden tests and instant verdicts. Start practising →
Section {{ sec.num }}

{{ sec.label }}

Python  /  {{ current.sectionLabel }}  /  {{ current.name }}

{{ current.name }}

Theory

{{ current.def }}

Why we use it

{{ rich.why }}

When to use it

{{ rich.when }}

Diagram

{{ rich.dg.caption }}

{{ tb.title }}
{{ c.v }}
{{ rich.dg.op }}
➜
{{ rich.dg.output.title }}
{{ c.v }}
{{ nd.label }}
{{ nd.sub }}
{{ nd.label }}
{{ nd.sub }}
{{ rich.dg.left.title }}
{{ it }}
{{ rich.dg.right.title }}
{{ it }}
Flowchart — how it works
{{ nd.text }}
{{ nd.text }}
◇ {{ nd.text }}
Yes → {{ nd.yes }}
No → {{ nd.no }}
Syntax
{{ current.syntax }}
Example
{{ current.example }}
▶ Try It Live — runs real Python 3.12 in your browser (first run loads the engine)
{{ liveOutput }}
{{ liveError }}
Key Points — click to check off as you learn
  • {{ pt.mark }} {{ pt.text }}

Share this topic