Sets for Unordered and Unique Data with Tuples in Python – Best Practices 2026
Sets are unordered collections of unique elements and are one of the most powerful tools for data deduplication, fast membership testing, and comparing datasets. Because sets require hashable elements, they work perfectly with tuples — making them ideal for storing unique combinations, coordinate pairs, or immutable records in data science workflows.
TL;DR — Key Properties of Sets
- Unordered and contain only unique elements
- Extremely fast membership testing (
inis O(1)) - Tuples can be elements of sets (they are hashable)
- Use
frozensetwhen you need a hashable set
1. Creating Sets and Adding Tuples
# Basic set from list (removes duplicates)
unique_regions = set(["North", "South", "North", "East", "South"])
print(unique_regions) # {'North', 'South', 'East'}
# Set containing tuples (common in data science)
coordinates = {(10.5, 20.3), (15.2, 25.7), (10.5, 20.3)} # duplicate tuple removed
print(coordinates)
2. Real-World Data Science Examples
import pandas as pd
# Small inline sample so this example runs as-is.
# In a real project you would load it: df = pd.read_csv("sales_data.csv")
df = pd.DataFrame({
"customer_id": [101, 102, 103, 104, 105, 106],
"customer_name": ["Ana", "Ben", "Chen", "Dana", "Eli", "Fay"],
"order_date": ["2026-01-05", "2026-01-12", "2026-02-03",
"2026-02-18", "2026-03-01", "2026-03-09"],
"amount": [1250.75, 890.50, 2340.00, 1780.25, 2615.40, 450.00],
"quantity": [3, 2, 5, 4, 6, 1],
"profit": [312.69, 222.63, 585.00, 445.06, 653.85, 112.50],
"region": ["North", "South", "East", "North", "West", "South"],
"category": ["Electronics", "Books", "Electronics", "Home", "Home", "Books"],
"rating": [5, 4, None, 3, 5, 4],
})
# Example 1: Unique customer-region pairs as tuples
unique_pairs = set((row.customer_id, row.region) for row in df.itertuples())
print(f"Unique customer-region combinations: {len(unique_pairs)}")
# Example 2: Deduplicating feature combinations
feature_combos = set()
for row in df.itertuples():
combo = (row.region, row.category) # tuple is hashable
feature_combos.add(combo)
# Example 3: Fast membership testing
high_value_customers = {(101, "North"), (203, "South")}
if (101, "North") in high_value_customers:
print("High-value North customer found")
3. Set Operations with Tuples
# Union, intersection, difference
set_a = {(101, "North"), (102, "South")}
set_b = {(102, "South"), (103, "East")}
combined = set_a | set_b # union
common = set_a & set_b # intersection
only_a = set_a - set_b # difference
print("Combined:", combined)
4. frozenset – When You Need a Hashable Set
# frozenset can be used as a dict key or set element
frozen_pairs = frozenset((row.customer_id, row.region) for row in df.itertuples())
config = {frozen_pairs: "Processed"}
5. Best Practices in 2026
- Use
set()whenever you need uniqueness or fast lookup - Store combinations as tuples inside sets (tuples are hashable)
- Use
frozensetwhen the set itself needs to be hashable - Convert back to list/tuple only when order matters
- Prefer sets over lists for deduplication and membership checks on large data
Why Tuples Fit Inside Sets (and Lists Do Not)
A set stores each element by its hash value, which is how membership checks stay fast regardless of set size. That only works if an element's hash can never change, so set members must be hashable. Tuples of numbers and strings qualify; lists, dicts and regular sets do not. Two tuples are considered the same element when they are equal item by item, so (101, "North") added twice is stored once.
Order inside the tuple matters: (1, 2) and (2, 1) are different elements. If you want an unordered pair — for example "A and B are connected" regardless of direction — normalise the tuple first with tuple(sorted(pair)) or use a frozenset.
Worked Example: Finding Unique and Repeated Pairs
visits = [
(101, "North"), (102, "South"), (101, "North"),
(103, "East"), (102, "South"), (104, "West"),
]
seen, repeated = set(), set()
for pair in visits:
if pair in seen: # fast hash-based lookup
repeated.add(pair)
seen.add(pair)
print(f"{len(visits)} visits, {len(seen)} unique pairs")
print("Repeated:", sorted(repeated))
# Unordered pairs: treat (A, B) and (B, A) as the same link
links = [("A", "B"), ("B", "A"), ("A", "C")]
undirected = {tuple(sorted(p)) for p in links}
print(sorted(undirected)) # [('A', 'B'), ('A', 'C')]
Wrapping results in sorted() gives a stable, readable output, because the iteration order of a set is not something you should rely on.
Common Mistakes
try:
bad = {[1, 2], [3, 4]} # lists are not hashable
except TypeError as e:
print("Error:", e)
try:
also_bad = {(1, [2, 3])} # tuple containing a list
except TypeError as e:
print("Error:", e)
empty = {} # this is a dict, not a set
print(type(empty), type(set()))
- Do not expect sets to keep insertion order; sort before displaying
- Use
frozensetwhen you need a set inside another set or as a dict key
Quick Summary
- Sets hold unique, hashable elements; tuples are the natural way to store composite values
- Tuple order matters — normalise pairs when direction does not
- Use set operations to compare groups of records quickly
Conclusion
Sets combined with tuples give you an extremely powerful way to handle unique, unordered data in Python data science. In 2026, use them for deduplicating customer-region pairs, feature combinations, fast lookups, and set operations. They reduce memory usage, eliminate duplicates automatically, and make your code faster and cleaner than using lists alone.
Next steps:
- Review any code where you manually check for duplicates or use
inon lists and replace them with sets containing tuples