library(tidyverse)
library(readxl)
library(janitor)
path <- "Power Query/300-399/342/PQ_Challenge_342.xlsx"
input <- read_excel(path, range = "A1:F19")
test <- read_excel(path, range = "H1:k13")
roll_left <- \(x) c(x[-1], x[1])
left_shift <- \(r) {
while(r[1] == "" || is.na(r[1])) r <- roll_left(r)
r
}
df <- input %>%
split(1:nrow(input)) %>%
map(~ left_shift(unlist(.x))) %>%
map_dfr(~ set_names(.x, names(input))) %>%
remove_empty("cols")
r1 = df %>%
filter(row_number() %% 2 == 1) %>%
select(Group1 = Col1, Group2 = Col2)
r2 = df %>%
filter(row_number() %% 2 == 0) %>%
select(Value1 = Col1, Value2 = Col2) %>%
mutate(across(everything(), as.numeric))
res = bind_cols(r1, r2) %>%
add_row(Group1 = NA, Group2 = NA, Value1 = NA, Value2 = NA, .before = 4) %>%
add_row(Group1 = NA, Group2 = NA, Value1 = NA, Value2 = NA, .before = 7) %>%
add_row(Group1 = NA, Group2 = NA, Value1 = NA, Value2 = NA, .before = 11)
all.equal(res, test, check.attributes = FALSE)
# [1] TRUEExcel BI - PowerQuery Challenge 342
excel-challenges
power-query
Group1 Group2 Transpose the table as shown.

Challenge Description
Group1 Group2 Transpose the table as shown.
Solutions
Logic:
Reads the workbook range needed for the challenge
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
from openpyxl import load_workbook
path = "Power Query/300-399/342/PQ_Challenge_342.xlsx"
input_df = pd.read_excel(path, usecols="A:F", nrows=18)
test_df = pd.read_excel(path, usecols="H:K", nrows=12)
def roll_left(x):
return x[1:] + [x[0]]
def left_shift(r):
while r[0] == "" or pd.isna(r[0]):
r = roll_left(r)
return r
df = pd.DataFrame([left_shift(row.tolist()) for _, row in input_df.iterrows()], columns=input_df.columns)
df = df.dropna(axis=1, how='all').loc[:, (df != "").any(axis=0)]
res = pd.concat([
df.iloc[::2][["Col1", "Col2"]].rename(columns={"Col1": "Group1", "Col2": "Group2"}).reset_index(drop=True),
df.iloc[1::2][["Col1", "Col2"]].rename(columns={"Col1": "Value1", "Col2": "Value2"}).apply(pd.to_numeric, errors='coerce').reset_index(drop=True)
], axis=1)
for idx in [3, 6, 10]:
res = pd.concat([res.iloc[:idx], pd.DataFrame([[np.nan]*4], columns=res.columns), res.iloc[idx:]], ignore_index=True)
print(res.equals(test_df)) # TrueLogic:
Reads the workbook range needed for the challenge
Applies the rule iteratively until the output is complete
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.