LeetCode 2885 - Rename Columns
This problem asks us to rename the column names of a Pandas DataFrame according to a fixed mapping. We are given a DataFrame named students with four columns: - id - first - last - age The goal is to return a DataFrame where these columns have been renamed to more descriptive…
Difficulty: 🟢 Easy
Topics: —
Solution
Problem Understanding
This problem asks us to rename the column names of a Pandas DataFrame according to a fixed mapping. We are given a DataFrame named students with four columns:
idfirstlastage
The goal is to return a DataFrame where these columns have been renamed to more descriptive names:
| Original Column | New Column |
|---|---|
id |
student_id |
first |
first_name |
last |
last_name |
age |
age_in_years |
Importantly, the actual data inside the DataFrame does not change. Only the column labels are modified. Every row and value must remain exactly the same.
The input represents a Pandas DataFrame containing student information. Each row corresponds to a student, and the columns store identifying and descriptive information. The expected output is the same DataFrame structure, but with renamed column headers.
Since this is a Pandas problem from LeetCode, the input is guaranteed to be a valid DataFrame containing the specified columns. There are no large-scale computational constraints because the operation is simply metadata transformation on column names.
An important observation is that we do not need to manually iterate through rows or reconstruct the DataFrame. Pandas already provides a built-in rename() method specifically for renaming columns efficiently.
A naive implementation might unnecessarily copy all rows into a new DataFrame or manually assign each column, but that introduces unnecessary complexity. Since the problem guarantees the required columns exist, we can safely apply a direct column rename mapping.
Potential edge cases include an empty DataFrame with no rows, because renaming columns should still work correctly, and DataFrames with many rows, where we want to avoid unnecessary row-by-row operations. Fortunately, Pandas column renaming works regardless of row count and operates efficiently.
Approaches
Brute Force Approach
A brute force approach would manually construct a new DataFrame by copying every column one by one under the new names.
For example, we could create a new DataFrame and assign:
student_id = students["id"]first_name = students["first"]last_name = students["last"]age_in_years = students["age"]
This approach works because each new column explicitly copies the corresponding original column, preserving the data while changing the names.
However, this method is unnecessarily verbose and potentially inefficient because it creates a new DataFrame and copies column references manually. It also becomes harder to maintain if the number of columns grows.
Optimal Approach
The key insight is that Pandas provides a built-in rename() method designed specifically for renaming columns.
We can define a dictionary that maps original column names to their new names and pass it to:
students.rename(columns=mapping)
This approach is clean, concise, and directly expresses the intent of the problem. Since only metadata changes, Pandas efficiently updates the column names without requiring row-by-row processing.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(n) | O(n) | Manually reconstructs a new DataFrame by copying columns |
| Optimal | O(1) | O(1) | Uses Pandas built-in column renaming |
The complexity for the optimal approach is effectively constant because the number of columns is fixed at four. More generally, if there were m columns, renaming would take O(m) time.
Algorithm Walkthrough
- Create a mapping dictionary that defines how each column should be renamed.
The dictionary pairs original column names with their desired replacements:
{
"id": "student_id",
"first": "first_name",
"last": "last_name",
"age": "age_in_years"
}
This mapping makes the transformation explicit and easy to understand.
2. Call the Pandas rename() method on the DataFrame.
We pass the mapping dictionary through the columns parameter so Pandas knows which column names should change.
3. Return the renamed DataFrame.
The resulting DataFrame contains exactly the same rows and values, only with updated column labels.
Why it works
The algorithm works because rename(columns=...) performs a deterministic mapping from old column names to new ones. Every specified column is replaced according to the dictionary, while the underlying row data remains untouched. Since the problem guarantees the required columns exist, the renaming operation always produces the correct output.
Python Solution
import pandas as pd
def renameColumns(students: pd.DataFrame) -> pd.DataFrame:
return students.rename(
columns={
"id": "student_id",
"first": "first_name",
"last": "last_name",
"age": "age_in_years",
}
)
The implementation is intentionally concise because Pandas already provides a built-in solution for this task.
The function receives the students DataFrame as input. It immediately calls the rename() method and passes a dictionary to the columns parameter. Each key in the dictionary represents an existing column name, and each value represents the replacement name.
After renaming, the updated DataFrame is returned. No row data is modified, and there is no need for iteration or manual copying.
Go Solution
Although this LeetCode problem is designed for Pandas in Python, a conceptual Go implementation using a table-like structure could look like this:
package main
type Student struct {
StudentID int
FirstName string
LastName string
AgeInYears int
}
func renameColumns(data []map[string]interface{}) []map[string]interface{} {
result := make([]map[string]interface{}, 0, len(data))
for _, row := range data {
newRow := map[string]interface{}{
"student_id": row["id"],
"first_name": row["first"],
"last_name": row["last"],
"age_in_years": row["age"],
}
result = append(result, newRow)
}
return result
}
Go does not have a built-in equivalent to Pandas DataFrames, so this solution uses a slice of maps to simulate tabular data. Instead of renaming metadata directly, we reconstruct rows with new field names.
Unlike Python, Go requires explicit handling of map creation and data copying because there is no native DataFrame abstraction.
Worked Examples
Example 1
Input DataFrame
| id | first | last | age |
|---|---|---|---|
| 1 | Mason | King | 6 |
| 2 | Ava | Wright | 7 |
| 3 | Taylor | Hall | 16 |
| 4 | Georgia | Thompson | 18 |
| 5 | Thomas | Moore | 10 |
Step 1: Create rename mapping
| Original | Renamed |
|---|---|
id |
student_id |
first |
first_name |
last |
last_name |
age |
age_in_years |
Step 2: Apply rename(columns=...)
Pandas updates only the column labels.
Step 3: Final DataFrame
| student_id | first_name | last_name | age_in_years |
|---|---|---|---|
| 1 | Mason | King | 6 |
| 2 | Ava | Wright | 7 |
| 3 | Taylor | Hall | 16 |
| 4 | Georgia | Thompson | 18 |
| 5 | Thomas | Moore | 10 |
Notice that none of the actual student data changes. Only the column names are modified.
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(1) | Only four fixed columns are renamed |
| Space | O(1) | No extra data structures proportional to input size are created |
More generally, if there were m columns, the renaming operation would take O(m) time because Pandas must process each column name once. Since this problem has exactly four columns, the runtime is effectively constant.
Test Cases
import pandas as pd
def renameColumns(students: pd.DataFrame) -> pd.DataFrame:
return students.rename(
columns={
"id": "student_id",
"first": "first_name",
"last": "last_name",
"age": "age_in_years",
}
)
# Example case from problem statement
students = pd.DataFrame({
"id": [1, 2, 3, 4, 5],
"first": ["Mason", "Ava", "Taylor", "Georgia", "Thomas"],
"last": ["King", "Wright", "Hall", "Thompson", "Moore"],
"age": [6, 7, 16, 18, 10]
})
result = renameColumns(students)
assert list(result.columns) == [
"student_id",
"first_name",
"last_name",
"age_in_years"
] # Provided example
# Empty DataFrame
students = pd.DataFrame(columns=["id", "first", "last", "age"])
result = renameColumns(students)
assert list(result.columns) == [
"student_id",
"first_name",
"last_name",
"age_in_years"
] # No rows, only columns
# Single row input
students = pd.DataFrame({
"id": [1],
"first": ["Alex"],
"last": ["Smith"],
"age": [20]
})
result = renameColumns(students)
assert result.iloc[0]["student_id"] == 1 # Single record preserved
assert result.iloc[0]["first_name"] == "Alex"
assert result.iloc[0]["last_name"] == "Smith"
assert result.iloc[0]["age_in_years"] == 20
# Large number of rows
students = pd.DataFrame({
"id": list(range(1000)),
"first": ["A"] * 1000,
"last": ["B"] * 1000,
"age": [10] * 1000
})
result = renameColumns(students)
assert len(result) == 1000 # Data preserved
assert "student_id" in result.columns # Rename successful
| Test | Why |
|---|---|
| Problem example | Verifies the expected transformation |
| Empty DataFrame | Ensures renaming works even without rows |
| Single row | Confirms data preservation for minimal input |
| Large dataset | Validates efficiency and correctness at scale |
Edge Cases
Empty DataFrame
One important edge case is an empty DataFrame that contains the required columns but no rows. A naive implementation that assumes rows exist could fail or behave unexpectedly. This implementation handles the case correctly because rename() only changes column metadata and does not depend on row data.
Single Student Record
A DataFrame containing only one student is another useful boundary case. Some implementations may accidentally alter data structure assumptions when the input size is very small. Since rename() operates only on column names, the row data remains completely intact.
Large Number of Rows
A very large DataFrame could expose inefficiencies in implementations that manually rebuild rows or iterate through records. The chosen solution avoids row-level processing entirely and simply updates column labels, making it efficient regardless of dataset size.