1.5. SAS PROCEDURES -> Equivalent in R
1.5.5. SAS PROC TRANSPOSE and its equivalent in R using pivot_wider() and pivot_longer()
Input Data: sales_data
| EMPLOYEE | PRODUCT | MONTH | SALES |
|---|---|---|---|
| Alice | Laptop | Jan | 5000 |
| Alice | Laptop | Feb | 5200 |
| Alice | Phone | Jan | 3000 |
| Alice | Phone | Feb | 3100 |
| Bob | Laptop | Jan | 4600 |
| Bob | Laptop | Feb | 4800 |
| Bob | Phone | Jan | 2800 |
| Bob | Phone | Feb | 2900 |
1 Objective A: Pivot PRODUCT values into columns (wide format)
We want:
| EMPLOYEE | MONTH | Laptop | Phone |
|---|---|---|---|
| Alice | Jan | 5000 | 3000 |
| Alice | Feb | 5200 | 3100 |
| Bob | Jan | 4600 | 2800 |
| Bob | Feb | 4800 | 2900 |
SAS Code
proc sort data=sales_data; by employee month;
proc transpose data=sales_data out=wide_product;
by employee month;
id product;
var sales;
run;
Explanation:
First, we sort by
EMPLOYEEandMONTHbecause PROC TRANSPOSE’sBYrequires sorted data.id product: turns values in PRODUCT into column names.var sales: fills the new columns with values from SALES.
R Code
# Dummy data for execution
library(dplyr)
library(tidyr)
sales_data <- tibble::tibble(
EMPLOYEE = c("Alice", "Alice", "Alice", "Alice", "Bob", "Bob", "Bob", "Bob"),
PRODUCT = c("Laptop", "Laptop", "Phone", "Phone", "Laptop", "Laptop", "Phone", "Phone"),
MONTH = c("Jan", "Feb", "Jan", "Feb", "Jan", "Feb", "Jan", "Feb"),
SALES = c(5000, 5200, 3000, 3100, 4600, 4800, 2800, 2900)
)
wide_product <- sales_data %>%
pivot_wider(
id_cols = c(EMPLOYEE, MONTH),
names_from = PRODUCT,
values_from = SALES
)
Explanation:
id_cols: defines keys to stay in rows.names_from: becomes column names (PRODUCT → Laptop, Phone).values_from: fills in those columns using SALES values.No sorting required!
2 Objective B: Reverse (wide → long format)
From the wide table above, convert back to original long form.
R Code
long_product <- wide_product %>%
pivot_longer(
cols = c(Laptop, Phone),
names_to = "PRODUCT",
values_to = "SALES"
)
Explanation:
cols: selects which columns to gather.names_to: stores column names inPRODUCT.values_to: stores numbers inSALES.
3 Objective C: Add a prefix to transposed column names
| EMPLOYEE | MONTH | SALE_Laptop | SALE_Phone |
|---|---|---|---|
| Alice | Jan | 5000 | 3000 |
| Bob | Jan | 4600 | 2800 |
wide_with_prefix <- sales_data %>%
pivot_wider(
id_cols = c(EMPLOYEE, MONTH),
names_from = PRODUCT,
values_from = SALES,
names_prefix = "SALE_"
)
Explanation:
Adds
"SALE_"to every PRODUCT column name.Useful for labeling metrics like SCORE_*, RATE_*, etc.
4 Advanced Explorations
1. Multiple Value Columns
| EMPLOYEE | PRODUCT | SALES | PROFIT |
|---|---|---|---|
| Alice | Laptop | 5000 | 1800 |
| Alice | Phone | 3000 | 1200 |
# Dummy data for execution
sales_multi <- tibble::tibble(
EMPLOYEE = c("Alice", "Alice"),
PRODUCT = c("Laptop", "Phone"),
SALES = c(5000, 3000),
PROFIT = c(1800, 1200)
)
pivot_wider(
data = sales_multi,
id_cols = EMPLOYEE,
names_from = PRODUCT,
values_from = c(SALES, PROFIT)
)
| EMPLOYEE | SALES_Laptop | SALES_Phone | PROFIT_Laptop | PROFIT_Phone |
|---|---|---|---|---|
| Alice | 5000 | 3000 | 1800 | 1200 |
2. Use names_sep with Multi-Key Columns
pivot_wider(
sales_data,
id_cols = EMPLOYEE,
names_from = c(PRODUCT, MONTH),
values_from = SALES,
names_sep = "_"
)
Output Columns: Laptop_Jan, Laptop_Feb, Phone_Jan, Phone_Feb
3. Use names_glue for Custom Naming
pivot_wider(
sales_data,
id_cols = EMPLOYEE,
names_from = c(PRODUCT, MONTH),
values_from = SALES,
names_glue = "{PRODUCT}_SALES_{MONTH}"
)
| EMPLOYEE | Laptop_SALES_Jan | Phone_SALES_Jan |
|---|---|---|
| Alice | 5000 | 3000 |
4. Reverse wide → long format
pivot_longer(
wide_product,
cols = c(Laptop, Phone),
names_to = "PRODUCT",
values_to = "SALES"
)
| EMPLOYEE | MONTH | PRODUCT | SALES |
|---|---|---|---|
| Alice | Jan | Laptop | 5000 |
5. Visualize Transposed Data
library(ggplot2)
ggplot(wide_product, aes(x = MONTH)) +
geom_col(aes(y = Laptop, fill = EMPLOYEE), position = "dodge") +
geom_col(aes(y = Phone, fill = EMPLOYEE), position = "dodge", alpha = 0.6)
Generates side-by-side bars for Laptop and Phone sales across employees and months.
**Summary Table**
| Feature | SAS: PROC TRANSPOSE |
R: pivot_wider() / pivot_longer() |
|---|---|---|
| Row → column (wide) | ID, VAR |
pivot_wider() |
| Column → row (long) | VAR |
pivot_longer() |
| Grouping key(s) | BY (needs sorting) |
id_cols = ... |
| Multiple value columns | One at a time, or merge later | values_from = c("col1", "col2") |
| Custom column naming | prefix=, delim= |
names_prefix=, names_sep=, names_glue= |
| Built-in flexibility | Functional | Extremely flexible |
| Reversibility | Manual | One-liners both directions |
**Resource download links**
1.5.5.-SAS-PROC-TRANSPOSE-and-its-equivalent-in-R-using-pivot_wider-and-pivot_longer.zip