library(tidyverse)
library(readxl)
library(glue)
input = read_excel("Power Query/PQ_Challenge_173.xlsx", range = "A1:B731")
test = read_excel("Power Query/PQ_Challenge_173.xlsx", range = "D1:H27")
result1 = input %>%
mutate(quarter = quarter(Date),
year = year(Date),
month = month(Date, label = TRUE, locale = "en"),
month_num = month(Date)) %>%
summarise(`Total Sale` = sum(Sale), .by = c("year", "quarter", "month", "month_num")) %>%
mutate(years_row = row_number(),
sales_perc = `Total Sale` / sum(`Total Sale`),
.by = "year") %>%
mutate(quarter_row = row_number(), .by = c("year","quarter")) %>%
mutate(display_year = ifelse(years_row == 1, year, NA_character_),
display_quarter = ifelse(quarter_row == 1, quarter, NA_integer_)) %>%
select(year, Year = display_year, Quarter = display_quarter, Month = month, month_num, `Total Sale`, `Sale %` = sales_perc)
totals = result1 %>%
summarise(`Total Sale` = sum(`Total Sale`), `Sale %` = sum(`Sale %`), .by = "year") %>%
mutate(Year = glue("{year} Total") %>% as.character(),
Quarter = NA_integer_,
Month = NA_character_,
month_num = NA_integer_) %>%
select(year, Year, Quarter, Month, `Total Sale`, `Sale %`)
result = bind_rows(result1, totals) %>%
arrange(year, month_num) %>%
select(-c(year, month_num))
all.equal(result, test, check.attributes = FALSE)
# [1] TRUE
#Excel BI - PowerQuery Challenge 173
excel-challenges
power-query
Date Sale Year Quarter Month Total Sale

Challenge Description
Date Sale Year Quarter Month Total Sale
Solutions
Logic:
Reads the workbook range needed for the challenge
Aggregates or ranks values at the relevant grouping level
Builds helper columns that drive the final output
Strengths:
- The R solution stays close to the workbook logic and keeps the transformation compact.
Areas for Improvement:
- The code assumes the workbook layout and selected ranges remain stable.
Gem:
- The best part of the solution is choosing the right intermediate shape before formatting the final output.
import pandas as pd
import numpy as np
input = pd.read_excel("PQ_Challenge_173.xlsx", sheet_name="Sheet1", usecols = "A:B", nrows=731)
test = pd.read_excel("PQ_Challenge_173.xlsx", sheet_name="Sheet1", usecols="D:H", nrows=26)
input["quarter"] = pd.PeriodIndex(input["Date"], freq="Q").quarter
input["year"] = input["Date"].dt.year
input["month"] = input["Date"].dt.strftime("%b")
input["month_num"] = input["Date"].dt.month
result1 = input.groupby(["year", "quarter", "month", "month_num"]).agg({"Sale": "sum"}).reset_index()
result1 = result1.sort_values(["year", "month_num"])
result1["years_row"] = result1.groupby("year").cumcount() + 1
result1["sales_perc"] = result1["Sale"] / result1.groupby("year")["Sale"].transform("sum")
result1["quarter_row"] = result1.groupby(["year", "quarter"]).cumcount() + 1
result1["display_year"] = np.where(result1["years_row"] == 1, result1["year"], np.nan)
result1["display_quarter"] = np.where(result1["quarter_row"] == 1, result1["quarter"], np.nan)
result1 = result1[["year", "display_year", "quarter", "display_quarter", "month", "month_num", "Sale", "sales_perc"]]
result1 = result1.rename(columns={"display_year": "Year", "display_quarter": "Quarter", "month": "Month"})
totals = result1.groupby("year").agg({"Sale": "sum", "sales_perc": "sum"}).reset_index()
totals["Year"] = totals["year"].astype(str) + " Total"
totals["Quarter"] = np.nan
totals["Month"] = np.nan
totals["month_num"] = np.nan
totals = totals[["year", "Year", "Quarter", "Month", "Sale", "sales_perc"]]
result = pd.concat([result1, totals]).sort_values(["year", "month_num"]).reset_index(drop=True)
result = result.drop(columns=["year", "month_num", "quarter"])
result = result.rename(columns = {"sales_perc": "Sale %", "Sale": "Total Sale"})
print(result.equals(test)) # TrueLogic:
Reads the workbook range needed for the challenge
Aggregates or ranks values at the relevant grouping level
Strengths:
- The Python version follows the same workbook rule in a direct pandas-oriented implementation.
Areas for Improvement:
- As with the R version, any workbook layout change would require small adjustments.
Gem:
- The implementation stays close to the source challenge instead of adding unnecessary abstraction.
Difficulty Level
This task is easy to moderate:
- The transformation rule is readable, but the final layout still requires a careful implementation.