Free Interactive Course · Spark + Scala

Columns & the Building Blocks

Every Spark transformation is built from Column expressions. Learn the six ways to reference a column, then the verbs that reshape a DataFrame: select, withColumn, alias, cast, and lit. Master this module and the rest of Spark is just vocabulary.

The dataset

This module uses the two DataFrames from Foundations:

peopleid, name, country, age, signup_date
ordersid, user_id, product, category, amount, qty, status, ordered_at
1.1

Referencing a column — the 6 ways

Before you can transform a column you have to name one, and Spark gives you six syntaxes that all produce the same Column object. They're interchangeable — teams pick one for consistency. Knowing all six means you can read anyone's code.

Signature
col(colName: String): Column
column(colName: String): Column   // identical to col
$"colName": Column                // needs import spark.implicits._
'colName: Column                  // Scala Symbol, same result
df("colName"): Column             // bound to a specific DataFrame
expr("colName + 1"): Column       // parses a SQL expression string

1. col("...") — the portable default

col (and its twin column) takes a column name as a string. It needs no DataFrame reference, so it's the safest choice in reusable helper functions:

Scala
import org.apache.spark.sql.functions.col

people.select(col("name"), col("country")).show()
Run the equivalent Spark SQL — edit it and press Run
SQL
⌘/Ctrl + Enter

2. $"..." — the idiomatic shorthand

With import spark.implicits._ in scope, $"name" is the community-favourite shorthand for col("name"). It also unlocks operators like $"age" + 1 and $"age" > 30:

Scala
people.select($"name", ($"age" + 1).as("age_next_year")).show()
Run the equivalent Spark SQL — edit it and press Run
SQL
⌘/Ctrl + Enter

3. df("...") — disambiguate after a join

When two DataFrames both have an id column, col("id") is ambiguous. people("id") binds the reference to a specific DataFrame — the one clean way to resolve it:

Scala
people.join(orders, people("id") === orders("user_id"))
  .select(people("name"), orders("product"))
  .show()
Run the equivalent Spark SQL — edit it and press Run
SQL
⌘/Ctrl + Enter

4. expr("...") — a SQL string as a Column

expr parses a SQL expression string into a Column — handy when the logic is easier to read as SQL, or built dynamically at runtime:

Scala
import org.apache.spark.sql.functions.expr

people.select(
  expr("name"),
  expr("CASE WHEN age >= 30 THEN 'senior' ELSE 'junior' END AS tier")
).show()
Run the equivalent Spark SQL — edit it and press Run
SQL
⌘/Ctrl + Enter
Gotcha: 'name (a Scala Symbol) also works and reads cleanly, but is deprecated in newer Spark/Scala combos — prefer $"name" or col. And never mix a bare string like "name" where a Column is required; only some methods (e.g. select, drop) accept both.
1.2

select & selectExpr — projecting columns

select chooses and computes columns — the projection step. It accepts column names, Column expressions, or a mix. selectExpr is a shortcut that takes SQL-expression strings directly:

Signature
def select(cols: Column*): DataFrame
def select(col: String, cols: String*): DataFrame
def selectExpr(exprs: String*): DataFrame
Scala
// select with Column expressions
people.select($"name", $"age", ($"age" * 12).as("age_in_months")).show()
Run the equivalent Spark SQL — edit it and press Run
SQL
🔮Before you run — how many rows come back?
⌘/Ctrl + Enter

selectExpr is the same projection expressed as SQL strings — less ceremony when the expressions get gnarly:

Scala
people.selectExpr("name", "age", "age * 12 AS age_in_months").show()
Run the equivalent Spark SQL — edit it and press Run
SQL
⌘/Ctrl + Enter
select replaces the projection — the result has only the columns you name. To add a column while keeping all the others, reach for withColumn (next).
1.3

withColumn & withColumnRenamed

withColumn is the workhorse: it returns a new DataFrame with a column added (or replaced, if the name already exists), keeping everything else. This is how you build up derived fields step by step.

Signature
def withColumn(colName: String, col: Column): DataFrame
def withColumnRenamed(existing: String, newName: String): DataFrame

1. Add a brand-new derived column

Scala
orders.withColumn("total", $"amount" * $"qty")
  .select($"product", $"amount", $"qty", $"total")
  .show()
Run the equivalent Spark SQL — edit it and press Run
SQL
⌘/Ctrl + Enter

2. Replace an existing column in place

Reuse the same name and withColumn overwrites it — here we round amount up to whole dollars:

Scala
orders.withColumn("amount", ceil($"amount"))
  .select($"product", $"amount")
  .show()
Run the equivalent Spark SQL — edit it and press Run
SQL
⌘/Ctrl + Enter

3. Rename a column

Scala
orders.withColumnRenamed("user_id", "customer_id")
  .select($"id", $"customer_id", $"product")
  .show()
Run the equivalent Spark SQL — edit it and press Run
SQL
⌘/Ctrl + Enter
Performance: chaining dozens of withColumn calls builds a deep, slow query plan. For many derived columns at once, do them in a single select with all the expressions — it's flatter and faster to analyze.
1.4

lit, cast & alias

Three small functions you'll use in almost every job. lit wraps a literal value as a Column (so you can mix constants into expressions). cast changes a column's type. alias / as renames a computed column.

Signature
def lit(literal: Any): Column
def col.cast(to: DataType): Column   // or cast("string")
def col.alias(name: String): Column  // as(name) is identical
Scala
orders.select(
  $"product",
  lit("USD").as("currency"),                 // a constant column
  $"amount".cast("int").as("amount_whole")   // double -> int
).show()
Run the equivalent Spark SQL — edit it and press Run
SQL
⌘/Ctrl + Enter
lit vs typedLit: use lit for scalars; use typedLit when you need Spark to preserve a specific Scala type such as a Seq or Map literal (covered in the Arrays and Maps modules).
P
PriyaFounder · Kettle & Co.now
Quick one for the finance sheet ☕ — from orders, give me each product, its line total (amount × qty) as a column called total, and tack on a constant currency column set to 'USD'. That's it!
🎯 Your mission From orders, return product, a computed total (amount × qty), and a literal currency column equal to 'USD'.
SQL
⌘/Ctrl + Enter

Ready for the full data stack?

These Spark functions are one piece. When you want pipelines, Kafka, lakehouse table formats, and a full end-to-end project, the Data Engineering course is free too.

Explore Data Engineering →

Comments

0

Join the conversation. Sign in to leave a comment — questions and feedback welcome.