Slicing columns in pandas is one of the most frequent operations — whether you're narrowing down features for modeling, selecting metrics for reporting, or cleaning up wide datasets. There are two main ways to slice columns: label-based with .loc[] (recommended for readability) and position-based with .iloc[] (fast for positional work). Both support slicing with start:stop:step syntax, just like lists.
Here’s a practical guide with real examples you can copy and adapt — including how to avoid common mistakes in 2026.
1. Setup & Sample Data
import pandas as pd
data = {
'Name': ['John', 'Mary', 'Peter', 'Anna', 'Mike'],
'Age': [25, 32, 18, 47, 23],
'Salary': [50000, 80000, 35000, 65000, 45000],
'Department': ['Sales', 'Engineering', 'Sales', 'HR', 'Engineering'],
'Bonus': [5000, 8000, 3000, 7000, 4000]
}
df = pd.DataFrame(data)
print(df.columns) # Index(['Name', 'Age', 'Salary', 'Department', 'Bonus'], dtype='object')
2. Label-Based Column Slicing with .loc[] (Recommended)
Use column names — works even if index is unsorted or columns are reordered.
# Columns from 'Age' to 'Department' (inclusive)
age_to_dept = df.loc[:, 'Age':'Department']
print(age_to_dept.columns) # ['Age', 'Salary', 'Department']
# Every other column from 'Age' to 'Bonus'
every_other = df.loc[:, 'Age':'Bonus':2]
print(every_other.columns) # ['Age', 'Department']
# From 'Salary' to end
salary_onward = df.loc[:, 'Salary':]
print(salary_onward.columns) # ['Salary', 'Department', 'Bonus']
3. Position-Based Column Slicing with .iloc[]
Use integer positions — ignores column names, faster for positional work.
# Columns 1 to 4 (Age, Salary, Department, Bonus) — stop is exclusive
pos_slice = df.iloc[:, 1:4]
print(pos_slice.columns) # ['Age', 'Salary', 'Department']
# Every second column from position 1 (Age) to end
every_second = df.iloc[:, 1::2]
print(every_second.columns) # ['Age', 'Department']
# Last 2 columns
last_two = df.iloc[:, -2:]
print(last_two.columns) # ['Department', 'Bonus']
4. Real-World Use Cases (2026 Examples)
Selecting feature subsets for modeling
# Numeric features only (assuming known positions)
features = df.iloc[:, 1:3] # Age and Salary
Excluding unwanted columns
# Drop 'Name' and 'Bonus' ? keep everything between
core_df = df.loc[:, 'Age':'Department']
Every other column (e.g., for sampling or testing)
sampled_cols = df.iloc[:, ::2] # every second column
5. Modern Alternative in 2026: Polars
For large datasets, Polars is often faster and more memory-efficient — slicing syntax is very similar.
import polars as pl
df_pl = pl.DataFrame(data)
# Slice by position (0-based)
subset_pl = df_pl[:, 1:4]
print(subset_pl.columns) # ['Age', 'Salary', 'Department']
Best Practices & Common Pitfalls
- Prefer
.loc[]with column names — more readable and safe when columns are reordered - Use
.iloc[]only for positional work (e.g., first 5 columns, last 3) - Stop is exclusive —
df.loc[:, 'A':'C']includes C - Negative step reverses order —
df.loc[:, ::-1]reverses columns - Always check column order with
df.columnsbefore positional slicing - For huge data, prefer Polars slicing — it's faster and more memory-efficient
Conclusion
Slicing columns with .loc[start:end:step] or .iloc[start:end:step] is a core pandas skill — it lets you quickly narrow focus to the data that matters. In 2026, prefer label-based .loc[] for clarity and safety, use .iloc[] for positional tasks, and reach for Polars when performance matters. Master slicing syntax, inclusive/exclusive rules, and negative steps, and you'll manipulate DataFrames with confidence and speed.
Next time you need a subset of columns — slice with .loc or .iloc first.