What you will be able to do
- Filter DataFrame rows with filter or where, using Column conditions or SQL expression strings
- Explode array and map columns into rows and predict which input rows disappear
- Choose between explode and explode_outer, and use the table-reference form in Databricks SQL
- Explode more than one array column, and flatten an array of structs into columns
1.Filtering rows with filter and where
Adding, renaming and dropping change a table's columns. Filtering and exploding change its rows: a filter removes rows, and an explode can multiply them. filter(condition) "Filters rows using the given condition" and returns a new DataFrame containing only the rows that satisfy it. The condition can take either of two forms: "A Column of BooleanType or a string of SQL expressions." So df.filter(df.age > 3) and df.filter("age > 3") return the same rows. The same reference page also demonstrates where, which takes the same kind of condition.
df.where(df.age == 2).show()
# +---+-----+-------+
# |age| name|subject|
# +---+-----+-------+
# | 2|Alice| Math|
# +---+-----+-------+
df.filter("age > 3").show()
# +---+-------+---------+
# |age| name| subject|
# +---+-------+---------+
# | 5| Bob| Physics|
# | 7|Charlie|Chemistry|
# +---+-------+---------+To combine Column conditions, the documented example wraps each comparison in parentheses and joins them with the & operator. It keeps only rows where age is over 3 and the subject is Physics, which leaves just Bob. Because the string form accepts SQL expressions, the whole condition can also be written as one SQL string.
Checkpoint 1 of 7· Fill the gap
Which operator completes this filter so that it keeps only rows where both conditions hold?
df.filter((df.age > 3) ? (df.subject == "Physics")).show()The documented example combines Column conditions with &, with each comparison in its own parentheses. The documented result is the single row for Bob, age 5, Physics.
Source: docs.databricks.comCheckpoint 2 of 7· Exam question
Which statement accurately distinguishes the DataFrame `withColumns` method from chaining several separate `withColumn` calls?
Correct answer: A — `withColumns` accepts a dictionary of column names mapped to expressions and applies every addition or replacement in one call, instead of calling `withColumn` repeatedly.
- A. `withColumns` accepts a dictionary of column name to `Column` expression pairs and applies all of the additions or replacements in a single planned step, which is functionally equivalent to but more concise than repeated `withColumn` calls. This is the current, supported API for adding several columns at once.
- B. Both `withColumns` and `withColumn` can add brand new columns from an expression, not just rename existing ones; renaming is instead the job of `withColumnRenamed`, so this description of the restriction is incorrect.
- C. `withColumns` is a current, actively documented DataFrame method and has not been removed; it remains available alongside `withColumn` for adding or replacing one or more columns.
- D. Neither method triggers eager execution or writes to storage; both `withColumns` and `withColumn` only build up a lazy transformation plan that executes when an action such as `show`, `count`, or `write` is called.
Sources1
2.Exploding array and map columns into rows
Nested data often arrives as an array column, for example one row per order with an array of item IDs. explode un-nests that array into rows. Take a DataFrame with three rows: (1, [1, 2, 3, NULL]), (2, []) and (3, NULL).
df.select('*', sf.explode('a')).show()
+---+---------------+----+
| i| a| col|
+---+---------------+----+
| 1|[1, 2, 3, NULL]| 1|
| 1|[1, 2, 3, NULL]| 2|
| 1|[1, 2, 3, NULL]| 3|
| 1|[1, 2, 3, NULL]|NULL|
+---+---------------+----+explode "Returns a new row for each element in the given array or map." The other columns are repeated on every output row, and the new values go into a column named col unless you alias it. Rows whose array is empty or NULL have no elements, so they produce no output rows. If you count rows before and after an explode, those parents disappear without any error. A map column works the same way, except that each entry becomes a row with two columns, key and value. You can rename both at once by passing two names to alias. The SQL reference also lists related generator functions: explode_outer, posexplode, posexplode_outer, inline and inline_outer.
Three rows come back, all from row 1, with the entries in columns named key and value. The entry for key 5 still gets its own row, with NULL in value, because that NULL is a value inside a non-null map. Rows 2 and 3 produce nothing.
Checkpoint 3 of 7· Check yourself
A DataFrame row has NULL in its array column. What does explode on that column do with that row?
explode produces rows only from elements, and a NULL collection has none, so the parent row vanishes without an error. explode_outer is the function that keeps a NULL row.
“If collection is NULL no rows are produced.”Source: docs.databricks.com
3.explode_outer and the SQL table-reference form
When parent rows must survive even if their array is NULL, use explode_outer. The SQL reference says: "To return a single row with NULLs for the array or map values use the explode_outer() function." The two queries below differ only in the function name.
> SELECT explode_outer(c1) AS elem, 'Spark' FROM VALUES(array(10, 20)), (null) AS T(c1);
10 Spark
20 Spark
NULL Spark
> SELECT explode(c1) AS elem, 'Spark' FROM VALUES(array(10, 20)), (null) AS T(c1);
10 Spark
20 Spark| Function | Input collection is NULL | Input collection has elements |
|---|---|---|
| explode | No rows produced | One row per array element, or per map key/value pair |
| explode_outer | A single row with NULLs | One row per array element, or per map key/value pair |
Those examples call explode in the SELECT list, which is the older style. From Databricks Runtime 12.2 LTS and in Databricks SQL, calling it from the SELECT list or a LATERAL VIEW clause is deprecated. Instead, invoke it as a table reference in the FROM clause and name its output column with a table alias.
> SELECT elem, 'Spark' FROM explode(array(10, 20)) AS t(elem);
10 Spark
20 SparkCheckpoint 4 of 7· Check yourself
On Databricks Runtime 12.2 LTS and above, how should a new Databricks SQL query invoke explode?
Calling explode from a LATERAL VIEW clause or the SELECT list is deprecated from 12.2 LTS. The function itself isn't deprecated; only those ways of calling it are.
“Invocation from the LATERAL VIEW clause or the SELECT list is deprecated. Instead, invoke explode as a table_reference.”Source: docs.databricks.com
Sources4
4.Exploding several arrays and arrays of structs
Some tables have two array columns to un-nest. The PySpark reference sets a hard rule: "Only one explode is allowed per SELECT clause." In the older SQL-list style, a second generator in the same SELECT list raises UNSUPPORTED_GENERATOR.MULTI_GENERATOR. In PySpark, the workaround is to explode one array per select and chain the selects. Every element of the first array is paired with every element of the second, so a 2-element array and a 3-element array produce six rows. In SQL from 12.2 LTS, two table-reference explodes in the FROM clause produce the same kind of pairing.
df = spark.sql('SELECT ARRAY(1,2) AS a1, ARRAY(3,4,5) AS a2')
df.select(
'*', sf.explode('a1').alias('v1')
).select('*', sf.explode('a2').alias('v2')).show()
+------+---------+---+---+
| a1| a2| v1| v2|
+------+---------+---+---+
|[1, 2]|[3, 4, 5]| 1| 3|
|[1, 2]|[3, 4, 5]| 1| 4|
|[1, 2]|[3, 4, 5]| 1| 5|
|[1, 2]|[3, 4, 5]| 2| 3|
|[1, 2]|[3, 4, 5]| 2| 4|
|[1, 2]|[3, 4, 5]| 2| 5|
+------+---------+---+---+JSON sources often produce arrays of structs. Exploding one gives a single struct column. Selecting s.* then expands the struct's fields into top-level columns, because the star operator selects all the fields within a given field. Together, these two steps turn an array of records into an ordinary table.
df = spark.sql('SELECT ARRAY(NAMED_STRUCT("a",1,"b",2), NAMED_STRUCT("a",3,"b",4)) AS a')
df.select(sf.explode('a').alias("s")).select("s.*").show()
+---+---+
| a| b|
+---+---+
| 1| 2|
| 3| 4|
+---+---+Checkpoint 5 of 7· Match them up
Match each input to what explode produces from it
Tap a term, then the definition that fits it.
Arrays produce a col column, maps produce key and value, expanding s.* turns struct fields into columns, and chained explodes pair every element with every element (2 × 3 = 6 rows in the example).
“The column produced by explode of an array is named col. The columns for a map are called key and value.”Source: docs.databricks.com
One recall item from page 1, since a flattened struct often leaves a column you no longer need: drop has two behaviours that are easy to get wrong.
Checkpoint 6 of 7· Check yourself
What does df.drop('no_such_column') do when the DataFrame has no column with that name?
drop returns a new DataFrame without the specified columns, and it is a no-op if the schema doesn't contain the given column name. A string is also treated literally as a column name, which differs from drop(col(colName)).
“This is a no-op if the schema doesn't contain the given column name(s).”Source: docs.databricks.com
Checkpoint 7 of 7· Exam question
A silver-layer notebook reads a DataFrame `customers_df` that includes an `internal_notes` column containing free-text data the downstream gold tables must never expose. The engineer needs to remove this column before writing the output, while keeping every other column unchanged. Which approach correctly does this?
Correct answer: A — Call `customers_df.drop("internal_notes")` and write the returned DataFrame, since `drop` returns a new DataFrame with the named column removed and leaves all other columns untouched.
- A. `drop` accepts one or more column names or `Column` objects and returns a new DataFrame with those columns removed from the schema while every remaining column is preserved, which is exactly what a sensitive-column removal step needs.
- B. `filter` (or `where`) removes rows based on a boolean condition; it changes which rows are kept, not which columns exist in the schema, so the sensitive column would still be present in the output.
- C. Assigning a null literal with `withColumn` replaces every value in that column with `null`, it does not remove the column from the schema, so the sensitive field would remain present with empty values.
- D. `dropDuplicates` removes duplicate rows based on the given column subset; it has no effect on which columns appear in the resulting schema, so the sensitive column would still be included.
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.explode keeps every parent row, and a NULL array just produces a row with a NULL value.Why is that wrong?
explode produces no rows for a NULL collection, so the parent row disappears. Use explode_outer to keep a single row with NULLs.
2.You can explode two array columns in the same select to un-nest them in one step.Why is that wrong?
Only one explode is allowed per SELECT clause. Chain one select per explode, which pairs every element of one array with every element of the other.
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.
“Filters rows using the given condition.”
↩︎ Filtering rows with filter and where“A Column of BooleanType or a string of SQL expressions.”
↩︎ Filtering rows with filter and where - 2.
“Returns a new row for each element in the given array or map.”
↩︎ Exploding array and map columns into rows“Only one explode is allowed per SELECT clause.”
↩︎ Exploding several arrays and arrays of structs“Only one explode is allowed per SELECT clause.”
↩︎ Exam trap 2 - 3.
“When unpacked with explode(), each value becomes a row in the output.”
↩︎ Exploding array and map columns into rows“Use the star operator (*) to select all fields within a given field.”
↩︎ Exploding several arrays and arrays of structs - 4.
“posexplode_outer table-valued generator function”
↩︎ Exploding array and map columns into rows“If collection is NULL no rows are produced.”
↩︎ explode_outer and the SQL table-reference form“Invocation from the LATERAL VIEW clause or the SELECT list is deprecated. Instead, invoke explode as a table_reference.”
↩︎ explode_outer and the SQL table-reference form“there must be no other generator function in the same SELECT list or UNSUPPORTED_GENERATOR.MULTI_GENERATOR is raised.”
↩︎ Exploding several arrays and arrays of structs“To return a single row with NULLs for the array or map values use the explode_outer() function.”
↩︎ Exam trap 1“If collection is NULL no rows are produced.”
↩︎ Prediction“The column produced by explode of an array is named col. The columns for a map are called key and value.”
↩︎ Checkpoint - 5.
“This is a no-op if the schema doesn't contain the given column name(s).”
↩︎ Exploding several arrays and arrays of structs