A window function performs calculations across a set of rows related to the current row, defined by a window specification, without collapsing the rows into a single output row.
Click to reveal answer
intermediate
How does a window specification define the rows for aggregation?
It defines partitioning (grouping rows), ordering (sorting rows), and frame boundaries (range of rows around the current row) to control which rows are included in the window.
Click to reveal answer
beginner
What is the difference between windowed aggregation and groupBy aggregation?
GroupBy aggregates collapse multiple rows into one per group, while windowed aggregation keeps all rows and adds aggregated values as new columns based on the window.
Click to reveal answer
intermediate
Example: What does this Spark code do?
<pre>from pyspark.sql import Window
from pyspark.sql.functions import sum
windowSpec = Window.partitionBy('category').orderBy('date').rowsBetween(Window.unboundedPreceding, 0)
df.withColumn('running_sum', sum('sales').over(windowSpec))</pre>
It calculates a running total of sales for each category, ordered by date, summing all sales from the start up to the current row.
Click to reveal answer
intermediate
What are frame boundaries in window functions?
Frame boundaries define the subset of rows relative to the current row included in the window, such as all previous rows, a fixed number before and after, or the entire partition.
Click to reveal answer
Which Spark function is used to define the window frame for aggregation?
AWindow.rowsBetween()
BWindow.orderBy()
CWindow.groupBy()
DWindow.partitionBy()
✗ Incorrect
Window.rowsBetween() sets the frame boundaries for the window, specifying which rows relative to the current row are included.
What does a windowed aggregation return compared to groupBy aggregation?
AOnly aggregated values
BOne row per group
CAll original rows with extra columns
DNo rows, just summary
✗ Incorrect
Windowed aggregation keeps all original rows and adds new columns with aggregated values computed over the window.
In Spark, which method partitions data for window functions?
ApartitionBy()
BorderBy()
CrowsBetween()
DgroupBy()
✗ Incorrect
partitionBy() divides data into groups for window calculations.
What does the following frame boundary mean? rowsBetween(Window.unboundedPreceding, 0)
AOnly current row
BAll rows from start to current row
CAll rows after current row
DAll rows in partition
✗ Incorrect
It includes all rows from the start of the partition up to the current row.
Which of these is NOT a valid window function in Spark?
Asum()
Bavg()
Ccount()
DgroupBy()
✗ Incorrect
groupBy() is a grouping method, not a window function.
Explain how windowed aggregations differ from regular groupBy aggregations in Spark.
Think about how many rows you get back and what extra data is added.
You got /4 concepts.
Describe the role of partitioning, ordering, and frame boundaries in defining a window specification.
Consider how these control which rows are included in calculations.
You got /4 concepts.
Practice
(1/5)
1. What is the main purpose of using windowed aggregations in Apache Spark?
easy
A. To perform calculations over a group of rows without collapsing them into a single result
B. To join two DataFrames based on a key column
C. To filter rows based on a condition
D. To sort the entire DataFrame globally
Solution
Step 1: Understand windowed aggregation concept
Windowed aggregations allow calculations like sums or averages over a set of rows related to the current row, without reducing the number of rows.
Step 2: Compare with other operations
Joins combine tables, filters remove rows, and sorting orders rows globally, but do not perform grouped calculations without collapsing rows.
Final Answer:
To perform calculations over a group of rows without collapsing them into a single result -> Option A
Quick Check:
Windowed aggregation = grouped calculation without row collapse [OK]
Hint: Windowed means grouped but keeps all rows [OK]
Common Mistakes:
Confusing windowed aggregation with join operations
Thinking windowed aggregation filters rows
Assuming windowed aggregation sorts globally
2. Which of the following is the correct way to define a window specification that partitions data by 'department' and orders by 'salary' in ascending order?
easy
A. Window.orderBy('department').partitionBy('salary')
B. Window.partitionBy('department').orderBy('salary')
C. Window.partitionBy('salary').orderBy('department')
D. Window.orderBy('salary').partitionBy('department')
Solution
Step 1: Recall window specification syntax
In Spark, window specs use partitionBy first to group, then orderBy to sort within groups.
Step 2: Check option order and columns
Window.partitionBy('department').orderBy('salary') correctly partitions by 'department' and orders by 'salary'. Other options reverse or swap columns incorrectly.
Final Answer:
Window.partitionBy('department').orderBy('salary') -> Option B
Quick Check:
partitionBy then orderBy = correct window spec [OK]
Hint: partitionBy groups first, orderBy sorts inside groups [OK]
Common Mistakes:
Swapping partitionBy and orderBy order
Using wrong columns in partitionBy or orderBy
Confusing partitionBy with filter
3. Given the following Spark code, what will be the output for the 'running_total' column?
from pyspark.sql import SparkSession
from pyspark.sql.window import Window
from pyspark.sql.functions import sum
spark = SparkSession.builder.getOrCreate()
data = [(1, 'A', 10), (2, 'A', 20), (3, 'A', 30), (4, 'B', 40)]
df = spark.createDataFrame(data, ['id', 'group', 'value'])
windowSpec = Window.partitionBy('group').orderBy('id').rowsBetween(Window.unboundedPreceding, Window.currentRow)
df = df.withColumn('running_total', sum('value').over(windowSpec))
df.orderBy('id').show()
medium
A. [10, 30, 60, 100]
B. [10, 20, 30, 40]
C. [10, 30, 60, 40]
D. [10, 20, 50, 40]
Solution
Step 1: Understand window specification
The window partitions by 'group' and orders by 'id'. The frame includes all rows from the start to the current row in that group.
Step 2: Calculate running totals per group
For group 'A': id=1 value=10 running_total=10; id=2 value=20 running_total=10+20=30; id=3 value=30 running_total=10+20+30=60. For group 'B': id=4 value=40 running_total=40.
Final Answer:
[10, 30, 60, 40] -> Option C
Quick Check:
Running total sums values up to current row per group [OK]
Hint: Running total sums values up to current row in partition [OK]
Common Mistakes:
Not partitioning by group, summing all rows
Misunderstanding rowsBetween frame
Mixing order of rows in calculation
4. Identify the error in the following Spark code snippet that tries to calculate a moving average over the last 2 rows including the current row:
from pyspark.sql.window import Window
from pyspark.sql.functions import avg
windowSpec = Window.partitionBy('category').orderBy('date').rowsBetween(-2, 0)
df = df.withColumn('moving_avg', avg('sales').over(windowSpec))
medium
A. partitionBy should be orderBy for moving average
B. orderBy column 'date' must be included in select
C. avg function cannot be used with window functions
D. rowsBetween frame is incorrect; it should be rowsBetween(-1, 0) for last 2 rows
Solution
Step 1: Understand rowsBetween frame
rowsBetween(-2, 0) includes current row and two preceding rows, totaling 3 rows, not 2.
Step 2: Correct frame for last 2 rows
To include current and previous row (2 rows total), use rowsBetween(-1, 0).
Final Answer:
rowsBetween frame is incorrect; it should be rowsBetween(-1, 0) for last 2 rows -> Option D
Quick Check:
rowsBetween(-1,0) = last 2 rows including current [OK]
Hint: rowsBetween counts rows including current, so -1 means one before [OK]
Common Mistakes:
Using wrong rowsBetween range for desired window size
Confusing partitionBy and orderBy roles
Thinking avg can't be used with window
5. You have a sales DataFrame with columns: 'store', 'date', and 'sales'. You want to calculate a 7-day moving average of sales per store, but some dates are missing for certain stores. Which approach correctly handles missing dates to compute the moving average using windowed aggregations?
hard
A. Fill missing dates with zero sales before applying a window partitioned by 'store' and ordered by 'date' with rowsBetween(-6, 0)
B. Use partitionBy('store') and orderBy('date') with rowsBetween(-7, 0) directly on original data without filling missing dates
C. Apply a global window without partitioning and order by 'date' only
D. Calculate moving average using groupBy('store', 'date') and avg('sales') without window functions
Solution
Step 1: Understand missing dates impact
Missing dates cause gaps in ordering, so rowsBetween(-6, 0) won't cover full 7 days if dates are missing.
Step 2: Fill missing dates with zero sales
Filling missing dates ensures continuous date sequence per store, so window frame covers exact 7 days.
Step 3: Apply window with partition and order
Partition by 'store', order by 'date', and use rowsBetween(-6, 0) to get 7-day moving average correctly.
Final Answer:
Fill missing dates with zero sales before applying a window partitioned by 'store' and ordered by 'date' with rowsBetween(-6, 0) -> Option A
Quick Check:
Fill gaps first, then window for accurate moving average [OK]
Hint: Fill missing dates to avoid gaps in window frame [OK]