Introdução
Os registros de pedidos da empresa varejista agora chegam em um arquivo CSV em vez de serem escritos diretamente na sua lista Python. Um arquivo armazena texto como 2 e 10.00; um cálculo precisa saber se esses valores significam texto, uma quantidade inteira ou um preço decimal. Ler os caracteres certos é apenas parte da leitura correta dos dados.
Você comparará a leitura padrão de strings do Spark, a inferência automática de tipos e um esquema explícito. Depois, aplicará o mesmo esquema a um segundo arquivo com a mesma ordem de campos. Os dados de negócio são propositalmente válidos aqui para que você se concentre no contrato entre colunas e valores. Um laboratório posterior trata explicitamente entradas ausentes e inválidas.
O ambiente fornece PySpark e dois arquivos CSV locais independentes de exemplo. Você deve compreender SparkSession, exibição de DataFrame, esquema e contagem de linhas do primeiro laboratório, além de Python básico. Não é necessário pandas, Hadoop, Hive, instalação nem estado anterior da VM. Use o Terminal.
Leia o cabeçalho e observe colunas de string
Nesta etapa, você relacionará as posições dos campos CSV à tabela que o Spark cria. Comece inspecionando o arquivo real:
cd /home/labex/project
cat /home/labex/project/data/orders.csv
A primeira linha nomeia sete colunas; as seis linhas seguintes são pedidos. Cada linha representa um pedido com um tipo de produto. O arquivo inclui status paid, pending e refunded; este laboratório lê todos eles sem aplicar uma regra de vendas.
spark.read cria um leitor de DataFrame. option("header", True) informa ao leitor que deve tratar a primeira linha do CSV como nomes de colunas, em vez de um registro de pedido. csv(input_path) nomeia o arquivo local. Sem inferência de tipos nem esquema fornecido, o leitor CSV produz colunas de string.
Salve e execute este programa completo. O here-document PYTHON entre aspas preserva o texto-fonte contido, e > grava o arquivo local. bigdata-python usa o ambiente PySpark preparado:
cat > /home/labex/project/read_orders.py <<'PYTHON'
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("ReadOrderCSV").master("local[2]").getOrCreate()
spark.sparkContext.setLogLevel("ERROR")
input_path = "/home/labex/project/data/orders.csv"
df = spark.read.option("header", True).csv(input_path)
df.printSchema()
df.orderBy("order_id").show(truncate=False)
print("Rows:", df.count())
spark.stop()
PYTHON
bigdata-python /home/labex/project/read_orders.py > /home/labex/project/output/string-orders.txt
cat /home/labex/project/output/string-orders.txt
Espere seis linhas e sete colunas de string, incluindo quantity e unit_price. O 2 exibido pode parecer numérico, mas printSchema identifica seu tipo real como string. orderBy("order_id") ordena as linhas exibidas por identificador para uma inspeção previsível; ordenar é separado de atribuir tipos.
header=True impediu que o cabeçalho se tornasse um sétimo registro. Isso não informou ao Spark que os preços devem ser decimais exatos nem que as datas devem permitir operações de data.
Compare inferência com um contrato explícito de dados
Nesta etapa, você declarará o significado de cada campo CSV. inferSchema=True pede ao Spark que examine os valores e deduza os tipos. Isso pode ser conveniente, mas o resultado depende dos dados observados; não é um acordo duradouro sobre preços nem arquivos futuros. Nestes dados de exemplo, a inferência identifica unit_price como double, um número de ponto flutuante.
Use um esquema explícito para o contrato pretendido. StructType é a coleção ordenada de campos. Cada StructField contém um nome, um tipo e True para permitir valores ausentes. StringType contém identificadores e texto de status; IntegerType contém quantidades; DecimalType(10, 2) contém preços exatos com dez dígitos no total e dois fracionários; DateType contém datas de calendário. Campos nullable permitem valores ausentes, mas não tornam automaticamente aceitável a ausência de informações de negócio.
Substitua o programa por esta versão. Ela imprime a descrição de tipos inferida para comparação e lê o mesmo arquivo com seu esquema explícito:
cat > /home/labex/project/read_orders.py <<'PYTHON'
from pyspark.sql.types import StructType, StructField, StringType, IntegerType, DecimalType, DateType
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("ReadOrderCSV").master("local[2]").getOrCreate()
spark.sparkContext.setLogLevel("ERROR")
order_schema = StructType([
StructField("order_id", StringType(), True),
StructField("customer_id", StringType(), True),
StructField("product_id", StringType(), True),
StructField("quantity", IntegerType(), True),
StructField("unit_price", DecimalType(10, 2), True),
StructField("order_status", StringType(), True),
StructField("order_date", DateType(), True),
])
input_path = "/home/labex/project/data/orders.csv"
inferred = spark.read.option("header", True).option("inferSchema", True).csv(input_path)
print("Inferred schema:", inferred.schema.simpleString())
df = (
spark.read
.option("header", True)
.option("dateFormat", "yyyy-MM-dd")
.schema(order_schema)
.csv(input_path)
)
print("Explicit schema:")
df.printSchema()
df.orderBy("order_id").show(truncate=False)
print("Rows:", df.count())
spark.stop()
PYTHON
bigdata-python /home/labex/project/read_orders.py > /home/labex/project/output/typed-orders.txt
cat /home/labex/project/output/typed-orders.txt
Localize o esquema explícito abaixo do resumo inferido. quantity deverá ser integer, unit_price decimal(10,2) e order_date date. Os seis registros ainda deverão estar presentes. A opção explícita dateFormat descreve as datas de entrada como ano-mês-dia, correspondendo a valores como 2026-10-14.
A ordem dos campos do esquema corresponde à ordem dos campos deste CSV. Um esquema fornecido não é uma instrução geral para reorganizar qualquer arquivo recebido pelo nome do cabeçalho. Para este recebimento de ordem conhecida, o contrato deixa claras as colunas e os tipos pretendidos. Um esquema também não substitui uma política de qualidade de dados; mais adiante, você aprenderá a tratar valores inválidos com segurança.
Aplique o mesmo esquema a um novo recebimento
Nesta etapa, você testará o contrato com um segundo arquivo válido. Primeiro, inspecione-o:
cat /home/labex/project/data/new-orders.csv
Ele tem os mesmos sete campos na mesma ordem, com dois novos pedidos. Preveja as mudanças: duas linhas de negócio em vez de seis, enquanto quantidade, preço e data mantêm seus tipos declarados.
A versão completa a seguir mantém o esquema explícito e muda o caminho de entrada. A comparação de inferência não é mais necessária para esta leitura normal:
cat > /home/labex/project/read_orders.py <<'PYTHON'
from pyspark.sql.types import StructType, StructField, StringType, IntegerType, DecimalType, DateType
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("ReadOrderCSV").master("local[2]").getOrCreate()
spark.sparkContext.setLogLevel("ERROR")
order_schema = StructType([
StructField("order_id", StringType(), True),
StructField("customer_id", StringType(), True),
StructField("product_id", StringType(), True),
StructField("quantity", IntegerType(), True),
StructField("unit_price", DecimalType(10, 2), True),
StructField("order_status", StringType(), True),
StructField("order_date", DateType(), True),
])
input_path = "/home/labex/project/data/new-orders.csv"
df = (
spark.read
.option("header", True)
.option("dateFormat", "yyyy-MM-dd")
.schema(order_schema)
.csv(input_path)
)
print("Explicit schema:")
df.printSchema()
df.orderBy("order_id").show(truncate=False)
print("Rows:", df.count())
spark.stop()
PYTHON
bigdata-python /home/labex/project/read_orders.py > /home/labex/project/output/new-typed-orders.txt
cat /home/labex/project/output/new-typed-orders.txt
Espere o7 com quantidade 2, preço 12.50, status paid e data 2026-10-16; o8 com quantidade 3, preço 4.00, status pending e data 2026-10-17. A contagem deverá ser 2. Confira os mesmos tipos integer, decimal e date em printSchema.
O arquivo original de seis pedidos permanece inalterado. Um esquema reutilizável permite que um novo recebimento entre na mesma lógica de processamento sem redefinir o significado de quantidade ou preço. A seguir, você usará essas colunas tipadas para selecionar pedidos e calcular o valor de cada pedido.
Resumo
Você leu corretamente um cabeçalho CSV, comparou leitura como strings e inferência e declarou um contrato explícito para identificadores, quantidades, preços decimais e datas. O mesmo esquema interpretou corretamente um segundo recebimento. A seguir, expressões de colunas tipadas permitirão filtrar linhas e calcular valores de pedidos.



