Slicing Columns in Pandas – Best Practices for Selecting Columns 2026
Selecting and slicing columns efficiently is a fundamental skill in Pandas data manipulation. In 2026, knowing the different ways to slice columns helps you write cleaner, faster, and more readable code.
TL;DR — Recommended Column Selection Methods
df[["col1", "col2"]]– Best for selecting specific columns by namedf.loc[:, "col1":"col3"]– Label-based slicing (inclusive)df.iloc[:, 0:5]– Position-based slicingdf.filter()– Flexible pattern-based selection
1. Basic Column Selection
import pandas as pd
# Create a small demo file so this example runs as-is
# (in your project, sales_data.csv is your real export)
import numpy as np
rng = np.random.default_rng(42)
n = 60
pd.DataFrame({
"order_date": pd.date_range("2026-01-01", periods=n, freq="3D"),
"customer_id": rng.integers(101, 121, n),
"customer_name": rng.choice([" ana", "ben ", "chen", "dana"], n),
"product_id": rng.integers(1, 9, n),
"region": rng.choice(["North", "South", "East", "West"], n),
"category": rng.choice(["Electronics", "Computers", "Books", "Home"], n),
"payment_method": rng.choice(["card", "cash", "wallet"], n),
"segment": rng.choice(["consumer", "business"], n),
"quantity": rng.integers(1, 6, n),
"amount": rng.uniform(50, 2500, n).round(2),
"discount": rng.choice([0.0, 0.05, 0.1, 0.2], n),
}).assign(
price=lambda d: (d["amount"] / d["quantity"]).round(2),
profit=lambda d: (d["amount"] * rng.uniform(0.05, 0.3, n)).round(2),
).assign(
ship_date=lambda d: d["order_date"] + pd.Timedelta(days=2),
status=lambda d: np.where(d["amount"] > 2000, "priority", "standard"),
).to_csv("sales_data.csv", index=False)
df = pd.read_csv("sales_data.csv", parse_dates=["order_date"])
# Most common and recommended way
sales_info = df[["order_date", "customer_id", "amount", "region"]]
# Select multiple columns by name
key_metrics = df[["amount", "quantity", "profit"]]
2. Label-based Column Slicing with .loc[]
# Slice columns by label (inclusive)
financial_cols = df.loc[:, "order_date":"profit"]
# Select from "customer_id" to "region" inclusive
customer_slice = df.loc[:, "customer_id":"region"]
3. Position-based Slicing with .iloc[]
# First 5 columns
first_five = df.iloc[:, :5]
# Columns from position 2 to 7 (exclusive end)
middle_cols = df.iloc[:, 2:8]
# Last 3 columns
last_three = df.iloc[:, -3:]
4. Advanced Column Selection with filter()
# Select columns containing a pattern
amount_cols = df.filter(like="amount")
# Select columns starting with "cust"
customer_cols = df.filter(regex="^cust")
# Select columns ending with "_id"
id_cols = df.filter(regex="_id$")
5. Best Practices in 2026
- Use
df[["col1", "col2"]]when you know exact column names — it's the most readable - Use
.loc[:, "start":"end"]for label-based range slicing - Use
.iloc[:, start:end]when working by position - Use
.filter()withlikeorregexfor pattern-based selection - Combine with
.reindex()or column lists for consistent column order
Selecting Columns Clearly
Column selection decides which variables continue through your analysis, so it pays to be explicit. A single name in brackets returns a Series, a list of names returns a DataFrame, and df.loc[:, "a":"c"] returns a contiguous range of columns by label, with both ends included.
For pattern-based selection, df.filter(like=...) and df.select_dtypes() avoid long hand-typed lists. Positional selection with iloc is useful when column names are unknown, but it breaks silently if the column order changes, so prefer names in production code.
Worked Example: Four Column Selections
The small orders table below shows each approach and the type of object it returns.
import pandas as pd
df = pd.DataFrame({
"order_id": [1, 2, 3],
"region": ["North", "South", "East"],
"price_usd": [19.5, 42.0, 7.25],
"tax_usd": [1.6, 3.4, 0.6],
"quantity": [2, 1, 5],
})
print(type(df["region"]).__name__)
print(df[["region", "quantity"]])
print(df.loc[:, "price_usd":"quantity"])
print(df.filter(like="_usd").columns.tolist())
print(df.select_dtypes("number").columns.tolist())
Notice that the label range includes quantity, the stop label, unlike positional slices. filter() and select_dtypes() adapt automatically when new matching columns are added later.
Practical Tips
When a script depends on specific columns, check that they exist before selecting them, for example with set(cols) - set(df.columns). A clear error at the start is easier to fix than a KeyError deep inside a pipeline.
Common Mistakes
- Expecting df["a", "b"] to select two columns; it needs a list.
- Assuming a loc column range excludes the stop label.
- Relying on iloc positions after columns have been reordered.
- Modifying a column subset and expecting the original to change.
Quick Summary
- df["col"] returns a Series; df[[...]] returns a DataFrame.
- loc label ranges include both ends.
- filter() and select_dtypes() select by pattern or type.
- Prefer names over positions for stable code.
Conclusion
Slicing columns effectively is essential for clean data manipulation. In 2026, the best practice is to use explicit column selection with df[["col1", "col2"]] for readability, .loc[] for label ranges, .iloc[] for positional slicing, and .filter() for pattern matching. Choosing the right method for each situation will make your code more maintainable and efficient.
Next steps:
- Review your current code and replace any loose column selection with explicit, readable slicing techniques