(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Como usar explode no PySpark: expandir arrays em linhas

João Barros 09 de July de 2026 4 min de leitura

Muitas fontes de dados guardam vários valores dentro de uma única célula, na forma de um array — por exemplo, a lista de produtos de cada encomenda ou as etiquetas de um artigo. Enquanto os dados estiverem "presos" dentro do array, é difícil contá-los, filtrá-los ou juntá-los a outras tabelas. No PySpark, a função explode transforma cada elemento do array na sua própria linha, sendo uma das ferramentas mais úteis para "achatar" estruturas aninhadas antes de agregar ou filtrar. É uma operação muito comum em dados vindos de APIs ou de ficheiros JSON, onde os campos repetidos aparecem quase sempre como listas dentro de uma coluna.

Pré-requisitos

  • Um ambiente com PySpark instalado (Databricks, Microsoft Fabric ou Spark local).
  • Uma SparkSession ativa (nos notebooks já existe como spark).
  • Conhecimentos básicos de DataFrames: criar, ver com show() e selecionar colunas.

Passo 1: Criar um DataFrame com uma coluna de array

Para o exemplo, vamos criar um pequeno DataFrame onde cada linha representa uma encomenda e a coluna produtos contém uma lista de artigos. Assim conseguimos ver o efeito do explode sem depender de dados externos.

from pyspark.sql import SparkSession
from pyspark.sql.functions import explode

spark = SparkSession.builder.getOrCreate()

dados = [
    (1, ["teclado", "rato", "monitor"]),
    (2, ["portátil"]),
    (3, []),
]
df = spark.createDataFrame(dados, ["encomenda_id", "produtos"])
df.show(truncate=False)

O resultado mostra três linhas, cada uma com um array na coluna produtos. Repara que a encomenda 3 tem um array vazio — vamos ver mais à frente porque isso é importante.

Passo 2: Aplicar explode para expandir o array

A função explode cria uma linha por cada elemento do array. Usamo-la dentro de um select (ou withColumn) para gerar uma nova coluna com os valores individuais.

from pyspark.sql.functions import explode

resultado = df.select("encomenda_id", explode("produtos").alias("produto"))
resultado.show(truncate=False)

Agora cada produto aparece na sua própria linha, mantendo o encomenda_id correspondente. A encomenda 1, que tinha três produtos, passou a ocupar três linhas. Repara que as restantes colunas do select são repetidas para cada elemento — é assim que o explode preserva o contexto de cada valor.

Passo 3: Manter as linhas com arrays vazios ou nulos

Há um detalhe importante: o explode elimina as linhas cujo array é vazio ou nulo. Foi por isso que a encomenda 3 desapareceu do resultado. Se precisas de manter essas linhas (com um valor nulo na nova coluna), usa explode_outer.

from pyspark.sql.functions import explode_outer

df.select("encomenda_id", explode_outer("produtos").alias("produto")).show(truncate=False)

Com explode_outer, a encomenda 3 mantém-se no resultado, com null na coluna produto. Esta diferença é fácil de esquecer e costuma explicar por que "faltam" registos depois de um explode.

Dica: se não tens a certeza se uma coluna pode conter nulos, usa explode_outer por defeito. É mais seguro do que descobrir mais tarde que perdeste linhas.

Passo 4: Obter também a posição de cada elemento

Às vezes queremos saber a ordem em que cada valor aparecia no array. A função posexplode devolve duas colunas: a posição (a começar em 0) e o valor.

from pyspark.sql.functions import posexplode

df.select("encomenda_id", posexplode("produtos").alias("posicao", "produto")).show(truncate=False)

Isto é útil, por exemplo, para identificar o primeiro produto de cada encomenda (posição 0) ou para reconstruir a ordem original mais tarde. Tal como o explode, também existe a variante posexplode_outer para manter as linhas vazias ou nulas.

Verificar o resultado

Para confirmar que a expansão correu bem, compara o número de linhas antes e depois. A soma dos tamanhos dos arrays deve corresponder ao total de linhas após o explode (com explode_outer, somam-se também as linhas vazias ou nulas).

print("Linhas originais:", df.count())
print("Linhas apos explode:", resultado.count())
resultado.groupBy("encomenda_id").count().show()

Se os números baterem certo e cada encomenda_id tiver o número de produtos esperado, a operação está correta.

Conclusão

Com explode, explode_outer e posexplode já consegues achatar arrays em linhas e escolher se queres manter (ou não) os registos vazios. O próximo passo natural é combinar o explode com groupBy para contar quantas vezes cada produto aparece, ou aplicar a mesma ideia a estruturas mais complexas. Já pensaste em como usarias o explode_outer para não perder encomendas sem produtos nos teus relatórios?