Operação Entre Conjuntos
Como fazer operação entre conjuntos na prática
Você provavelmente já viu isso na faculdade. União, interseção, diferença, diferença simétrica. Todo mundo aprende com exemplos bonitinhos usando A = {1, 2, 3} e B = {2, 3, 4}. O problema é que na vida real os dados nunca vêm assim. Eles chegam bagunçados, com tipos misturados, valores nulos e duplicados que ninguém pediu. A operação entre conjuntos em si é simples de entender. A coisa chata é colocar ela para funcionar quando você tem milhares de registros e precisa de performance.
O que exatamente é operação entre conjuntos
Conjuntos são coleções de elementos distintos. Não importa a ordem. Se você repetir um elemento, o conjunto simplesmente ignora. As operações básicas são: União: todos os elementos que estão em pelo menos um dos conjuntos. Intersection: apenas os elementos que estão em ambos. Diferença: elementos que estão no primeiro mas não no segundo. Diferença simétrica: elementos que estão em um ou outro, mas não em ambos. Em matemática pura isso é elegante. Em programação, cada linguagem implementa de um jeito diferente, e as armadilhas mudam conforme o tipo de dado.
Método com Python e sets nativos
Se você está no Python, a forma mais direta é usar o tipo set. Ele já traz essas operações como métodos embutidos. União usa o operador | ou o método union(). Interseção usa & ou intersection(). Diferença usa - ou difference(). Diferença simétrica usa ^ ou symmetric_difference().

a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
uniao = a | b {1, 2, 3, 4, 5, 6}
intersecao = a & b {3, 4}
diferenca = a - b {1, 2}
diff_simetrica = a ^ b {1, 2, 5, 6}
Isso funciona bem para dados pequenos. Sets em Python são implementados como hash tables, então a busca por pertinência é O(1) em média. Para conjuntos com até algumas dezenas de milhares de elementos, o tempo de execução fica em milissegundos. Tem um detalhe que muita gente esquece. Elementos dentro de um set precisam ser hashable. Isso significa listas, dicionários e outros sets dentro dele não podem existir. Só números, strings, tuplas e tipos imutáveis funcionam. Se você tentar passar uma lista, vai receber um erro TypeError na hora.
Quando os dados não são tão simples assim
Eu precisei resolver um problema há algum tempo envolvendo operação entre conjuntos com dados de dois sistemas diferentes. Um sistema usava strings com espaços extras e maiúsculas em lugares estranhos. O outro usava números em formato float. Obviamente uma interseção direta não funcionava. A solução foi normalizar antes. Strip nos strings, lowercase, e converter tudo para o mesmo tipo. No caso dos floats, arredondar para duas casas decimais antes de comparar. Sem essa normalização, a interseção retornava vazia porque "João Silva" não era igual a "joão silva" para o Python.
lista_a = ["João Silva", "Maria Santos", "Pedro Costa"]
lista_b = ["joão silva", "Carlos Lima", "Maria Santos"]
conjunto_a = set(item.strip().lower() for item in lista_a)
conjunto_b = set(item.strip().lower() for item in lista_b)
intersecao = conjunto_a & conjunto_b {'joão silva', 'maria santos'}
Pandas para datasets maiores
Quando o volume cresce e você já está trabalhando com DataFrames, perder tempo convertendo para sets manuais não compensa. O pandas tem funções específicas para isso. O método merge com how='inner' faz interseção. How='outer' faz união. How='left' com indicator revela o que sai na diferença. É menos intuitivo no começo, mas escala muito melhor. Em datasets com centenas de milhares de linhas, o pandas é tipicamente de 5 a 10 vezes mais rápido que looping manual em Python puro. A diferença depende do hardware, claro. Em uma máquina com 16GB de RAM e processador padrão, uma união de dois DataFrames com 200 mil linhas cada leva cerca de 300 milissegundos. O mesmo feito manualmente com sets levaria alguns segundos.

Armadilhas comuns que eu já vi acontecerem
Ordem dos operandos na diferença. A diferença A - B não é a mesma que B - A. Muita gente assume que sim e começa a depender disso sem perceber. Em operações mais complexas, onde você encadeia várias diferenças, isso gera bugs silenciosos que só aparecem meses depois. Duplicados disfarçados. Dados vindos de fontes diferentes podem ter o mesmo valor representado de formas distintas. Um código de produto como "PROD-001" em uma tabela e "prod-001" em outra. O set trata como elementos diferentes. A normalização é obrigatória, não opcional. Performance com sets grandes. Sets funcionam bem, mas se você precisar fazer operação entre conjuntos repetidamente em loops, o overhead de criar novos sets a cada iteração pode se tornar significativo. Nesse caso, usar inplace operations ou Work com cópias de conjuntos já existentes economiza memória e tempo.
Limitações que ninguém gosta de admitir
Sets não mantêm ordem. Isso parece óbvio, mas em casos você precisa da ordem original dos dados. Se a ordem importa para o seu downstream, sets não são a ferramenta certa. Você pode converter para lista depois, mas a ordem original será perdida. Não lidam bem com dados faltantes. None e NaN não são iguais entre si em sets. Dois NaN no mesmo set são considerados elementos diferentes. Se seus dados têm missing values, você precisa tratá-los antes de aplicar qualquer operação. Para dados massivos que não cabem na memória, sets nativos do Python vão estourar. Nesse cenário, o ideal é usar bibliotecas como Dask ou Polars, que permitem operação entre conjuntos de forma lazy e distribuída. Ou simplesmente trabalhar com SQL, onde UNION, INTERSECT e EXCEPT são operadoras nativas do padrão e o otimizador de query cuida da maioria dos problemas de performance.
Alternativa rápida com SQL
Se você já tem os dados em um banco relacional, muitas vezes a operação mais eficiente é deixar o banco fazer o trabalho. UNION remove duplicatas automaticamente. Se você quer manter duplicatas, usa UNION ALL. A diferença é importante porque UNION ALL é significativamente mais rápido, mas o resultado pode conter repetições que talvez você não queira. Índices fazem toda a diferença aqui. Uma coluna indexada em tabelas grandes pode transformar uma operação que levaria minutos em algo que leva segundos. Sem índice, o banco precisa de scan completo em ambas as tabelas, e o custo cresce linearmente com o tamanho dos dados.

Resumo sem conclusionzinha
Operação entre conjuntos é fundamental em praticamente qualquer fluxo de dados. A escolha da ferramenta depende do volume, do tipo de dado e se a ordem importa. Sets do Python são rápidos para coisas pequenas. Pandas escala melhor. SQL é a opção certa quando os dados já estão em banco. Normalização prévia resolve a maioria dos problemas de matching, e tratar missing values antes de tudo evita surpresas.
Galeria
-
Operações com conjuntos: saiba como resolver - Mundo Educação -
Operações com Conjuntos: Você sabe como são? Veja mais em nosso Insta ...