Skip to content

Data Engineer Associate · Domain 3: Data Transformation and Modeling · 22% of the exam

Task 3.3: Manipulate columns, rows, and table structures by adding, dropping, splitting, renaming column names, applying filters, and exploding arrays.

withColumn, drop, split, withColumnRenamed, filter and where, explode and explode_outer, and ALTER TABLE for column changes.

Study it

  • Adding, dropping, splitting and renaming columns; filters; explode

    Lesson coming

Sample questions

Try each one before opening the answer. Every option is explained, with the Databricks documentation page that proves it.

Question 1 · choose 1

The DataFrame orders has an ARRAY column items. Some orders have an empty array or a NULL value in items. The silver table needs one row per item, and orders without items must still appear once with a NULL item. Which expression should the data engineer use?

  1. Aorders.select('order_id', explode('items').alias('item'))
  2. Borders.select('order_id', split('items', ',').alias('item'))
  3. Corders.select('order_id', posexplode('items').alias('pos', 'item'))
  4. Dorders.select('order_id', explode_outer('items').alias('item'))
Show the answer and why
  • Aorders.select('order_id', explode('items').alias('item'))

    Incorrect

    explode produces no rows for a NULL or empty array, so orders without items are dropped.

  • Borders.select('order_id', split('items', ',').alias('item'))

    Incorrect

    split turns a string into an array; it does not create one row per element and does not accept an array column.

  • Corders.select('order_id', posexplode('items').alias('pos', 'item'))

    Incorrect

    posexplode adds each element's position but, like explode, returns no rows for NULL or empty arrays.

  • Dorders.select('order_id', explode_outer('items').alias('item'))

    Correct

    explode_outer returns a row with a NULL element when the array is NULL or empty, so every order is kept.

explode and posexplode drop rows whose array is NULL or empty. Their _outer variants keep such rows with a NULL value.

Question 2 · choose 1

A DataFrame has a column full_name with values like 'Ada Lovelace'. The data engineer runs df.withColumn('first_name', <expr>) and needs first_name to hold 'Ada' on the same row. Which expression should replace <expr>?

  1. Asplit('full_name', ' ').getItem(0)
  2. Bexplode(split('full_name', ' ')).alias('first_name')
  3. Csplit('full_name', ' ')
  4. Dtrim('full_name')
Show the answer and why
  • Asplit('full_name', ' ').getItem(0)

    Correct

    split returns an array of the parts, and getItem(0) picks the first element into the new column.

  • Bexplode(split('full_name', ' ')).alias('first_name')

    Incorrect

    explode turns the array into separate rows, so each name part lands on its own row.

  • Csplit('full_name', ' ')

    Incorrect

    This stores the whole array, ['Ada', 'Lovelace'], in first_name instead of its first element.

  • Dtrim('full_name')

    Incorrect

    trim only removes leading and trailing spaces; the full name stays together.

Splitting a string into columns is split plus getItem. explode is the tool when each part should become its own row.

Question 3 · choose 1

A DataFrame with 40 columns has a column cust_id that must be renamed customer_id. All other columns must stay. Which expression does this?

  1. Adf.select(col('cust_id').alias('customer_id'))
  2. Bdf.withColumn('customer_id', col('cust_id'))
  3. Cdf.withColumnRenamed('cust_id', 'customer_id')
  4. Ddf.toDF('customer_id')
Show the answer and why
  • Adf.select(col('cust_id').alias('customer_id'))

    Incorrect

    select returns only the listed columns, so the other 39 columns are dropped.

  • Bdf.withColumn('customer_id', col('cust_id'))

    Incorrect

    withColumn adds a copy under the new name and keeps cust_id as well.

  • Cdf.withColumnRenamed('cust_id', 'customer_id')

    Correct

    withColumnRenamed renames one column and returns all the others unchanged.

  • Ddf.toDF('customer_id')

    Incorrect

    toDF assigns new names to all columns by position and needs one name per column.

withColumnRenamed (or withColumnsRenamed for several) renames in place; alias works inside a select that lists the columns you keep.

Question 4 · choose 1

Before writing a silver table, the columns _rescued_data and ingest_ts must be removed from the DataFrame df, and every row must be kept. Which expression does this?

  1. Adf.select('_rescued_data', 'ingest_ts')
  2. Bdf.drop('_rescued_data', 'ingest_ts')
  3. Cdf.dropna(subset=['_rescued_data', 'ingest_ts'])
  4. Ddf.dropDuplicates(['_rescued_data', 'ingest_ts'])
Show the answer and why
  • Adf.select('_rescued_data', 'ingest_ts')

    Incorrect

    select keeps the listed columns and removes the rest, the opposite of what is needed.

  • Bdf.drop('_rescued_data', 'ingest_ts')

    Correct

    drop returns a DataFrame without the named columns, with every row kept.

  • Cdf.dropna(subset=['_rescued_data', 'ingest_ts'])

    Incorrect

    dropna removes rows that have nulls in those columns; the columns themselves stay.

  • Ddf.dropDuplicates(['_rescued_data', 'ingest_ts'])

    Incorrect

    dropDuplicates works on rows, not columns, so _rescued_data and ingest_ts would stay in the DataFrame.

drop removes columns. dropna and dropDuplicates remove rows.

Question 5 · choose 1

A silver DataFrame must keep only rows where status is 'shipped' and amount is greater than 100. Which PySpark filter is correct?

  1. Adf.filter(col('status') == 'shipped' and col('amount') > 100)
  2. Bdf.filter(col('status') == 'shipped' & col('amount') > 100)
  3. Cdf.filter((col('status') == 'shipped') | (col('amount') > 100))
  4. Ddf.filter((col('status') == 'shipped') & (col('amount') > 100))
Show the answer and why
  • Adf.filter(col('status') == 'shipped' and col('amount') > 100)

    Incorrect

    Python's and keyword cannot combine Column conditions; PySpark uses the & operator for this.

  • Bdf.filter(col('status') == 'shipped' & col('amount') > 100)

    Incorrect

    & binds tighter than == and >, so without parentheses the expression is grouped wrongly.

  • Cdf.filter((col('status') == 'shipped') | (col('amount') > 100))

    Incorrect

    | is OR, so rows meeting either condition would be kept.

  • Ddf.filter((col('status') == 'shipped') & (col('amount') > 100))

    Correct

    Each comparison is wrapped in parentheses and combined with &, which is how PySpark expresses AND.

In PySpark, combine Column conditions with &, | and ~, and put each comparison in parentheses. A SQL string such as "status = 'shipped' AND amount > 100" also works.

Practise domain 3 →Practise all domains →