The everyday API: select/selectExpr and filter for rows and columns, withColumn/lit/cast/when to shape them, and sort/distinct/limit — plus the null and dedupe traps, chained into a readable, performant pipeline.
⏱ 6 min readTopics chapter readerLevel · Structured APIs
01 · Overview
Start here
⏱ 5 min · Topic 1 of 8
This chapter covers the DataFrame steps you use every day: choose columns and rows, add columns, sort and remove repeats.
Each step returns a new DataFrame, and nothing runs until an action such as show() (chapter 5).
The examples use orders.csv from chapter 3, read with inferSchema=True, and the customers:
customers
customer_id
name
country
1
Asha
IN
2
Ben
GB
3
Carla
US
4
Dev
NULL
5
Omar
IN
Two NULL values matter in this chapter. Dev has no country, and order 105 has no amount.
02 · Choose
select and filter
⏱ 4 min · Topic 2 of 8
select keeps the columns you name. filter keeps the rows where a condition is true. col("status") points to a column by its name:
The first when that is true wins. Order 105 has no amount, so both tests are unknown, and it falls to otherwise.
Without otherwise, a row that matches no when gets NULL, not its old value. For example, when(col("amount") >= 50, "large") alone sizes only orders 103 and 106. The other four get NULL.
cast: change a type
cast changes the type of a column. Here a made-up table holds amounts as text, and one is broken:
Column.try_cast exists from PySpark 4.0. Count the NULL values it makes, so bad data does not hide.
Watch out
In Spark 3, ANSI mode was off by default, so a failed cast quietly gave NULL. The same code can fail after an upgrade to Spark 4. Check spark.sql.ansi.enabled.
05 · Order
Sorting, distinct and limit
⏱ 7 min · Topic 5 of 8
distinct removes repeated rows. orderBy sorts. limit(n) keeps the first n rows:
Without limit(2), the result is paid, pending and refunded.
distinct and orderBy are wide steps: they move rows between tasks in a shuffle (chapter 5). On big data, filter and select first, so they move less data.
Where do NULL values go in a sort? Here are the amounts, largest first:
Splitting the chain over many lines costs nothing. Spark builds one plan from the whole chain.
To add many columns, do not call withColumn in a long loop. Each call makes the plan bigger, and a very big plan can take minutes to build before any task runs.
Use one select(*columns) with all the new columns, or withColumns({...}), which takes many columns at once (Spark 3.3 and later).
07 · Recap
Recap
⏱ 4 min · Topic 7 of 8
Each step has a cost and one trap to remember:
Step
Moves data?
The trap
select, filter, withColumn
No
filter drops rows whose condition is NULL.
when without otherwise
No
Rows that match no when get NULL.
cast
No
Fails on bad text in Spark 4. try_cast gives NULL.
distinct, orderBy
Yes, a shuffle
Expensive on big data.
dropDuplicates(subset)
Yes, a shuffle
Keeps any one row, not the latest.
Check yourself: filter country != "IN" gives 2 customers and its opposite gives 2. Where is the fifth? (Answer: Dev, whose country is NULL.)
08 · Next Chapter
Next Chapter
You can now choose, add, sort and clean columns and rows.
⏱ 3 min · Topic 8 of 8
Next chapter
Working with Different Data Types
You can now choose, add, sort and clean columns and rows.
Next, the values inside them: text, numbers, dates, NULL and nested data.