Question

Selecting Multiple Columns in a Pandas DataFrame in Python

pythonpandasdataframeselectindexing

Question

How can I select columns a and b from a Pandas DataFrame df and store them in a new DataFrame called df1?

Example DataFrame:

import pandas as pd

df = pd.DataFrame(
    {
        'a': [2, 3],
        'b': [3, 4],
        'c': [4, 5]
    },
    index=[1, 2]
)

This DataFrame looks like:

   a  b  c
1  2  3  4
2  3  4  5

I tried the following, but they did not work as expected:

df1 = df['a':'b']
df1 = df.ix[:, 'a':'b']

What is the correct way to select multiple columns and create a new DataFrame?

Short Answer

By the end of this page, you will understand how to select one or more columns from a Pandas DataFrame, why column selection syntax works the way it does, and how to safely create a new DataFrame containing only the columns you need.

Concept

In Pandas, a DataFrame is a table with rows and columns. Selecting columns is one of the most common operations when working with data.

To select multiple columns, you usually pass a list of column names:

df1 = df[['a', 'b']]

This returns a new DataFrame containing only columns a and b.

Why this matters:

  • You often need only a subset of columns for analysis.
  • Many machine learning and reporting tasks start by choosing relevant columns.
  • Clean column selection makes code easier to read and maintain.

A key beginner point is this:

  • df['a'] selects one column and returns a Series.
  • df[['a', 'b']] selects multiple columns and returns a DataFrame.

Your unsuccessful attempt df['a':'b'] does not mean “columns from a to b”. In that form, Pandas interprets the slice more like a row slice, not a column slice.

Also, .ix is deprecated and should not be used in modern Pandas code. Use .loc or direct column-list selection instead.

Mental Model

Think of a DataFrame like a spreadsheet.

  • Each column is a labeled vertical strip: a, b, c.
  • Each row is a horizontal record.

If you want columns a and b, imagine highlighting those two spreadsheet columns and copying them into a new sheet.

In Pandas:

  • df['a'] = copy one vertical strip
  • df[['a', 'b']] = copy two vertical strips

The extra square brackets matter because Pandas needs a list when you want more than one column.

Take Quiz

Syntax and Examples

The most common way to select multiple columns is:

df1 = df[['a', 'b']]

Example

import pandas as pd

df = pd.DataFrame(
    {
        'a': [2, 3],
        'b': [3, 4],
        'c': [4, 5]
    },
    index=[1, 2]
)

df1 = df[['a', 'b']]
print(df1)

Output:

   a  b
1  2  3
2  3  4

Using .loc

You can also select all rows and specific columns with .loc:

df1 = df.loc[:, ['a', 'b']]

This means:

  • : → all rows
  • ['a', 'b'] → only these columns

Selecting a range of columns by label

If your columns are in order and you want a label range, .loc can do that:

df1 = df.loc[:, 'a':'b']

This works because .loc supports label-based slicing on columns.

For this DataFrame, it returns columns a and b.

Step by Step Execution

Consider this code:

import pandas as pd

df = pd.DataFrame(
    {
        'a': [2, 3],
        'b': [3, 4],
        'c': [4, 5]
    },
    index=[1, 2]
)

df1 = df[['a', 'b']]

Step by step:

  1. df is created with 3 columns: a, b, and c.
  2. [['a', 'b']] is a Python list containing two column names.
  3. Pandas looks for columns named a and b.
  4. It builds a new DataFrame containing just those columns.
  5. df1 now refers to that new DataFrame.

Result:

print(df1)

Output:

   a  b
1  2  3
2  3  4

Now compare with this:

col = df['a']

Here, only one column name is given, so Pandas returns a Series, not a DataFrame.

print(type(col))   # pandas.core.series.Series
print(type(df1))   # pandas.core.frame.DataFrame

Real World Use Cases

Selecting multiple columns is used constantly in real data work.

Common scenarios

  • Preparing input features for machine learning
    • Select only the columns used for training.
  • Cleaning imported CSV data
    • Keep only relevant fields like name, email, and age.
  • Generating reports
    • Create a smaller table with just the columns needed for display.
  • API response shaping
    • Return selected fields from a larger dataset.
  • Data validation
    • Check required columns before processing.

Example

user_df = df[['a', 'b']]

In a real project, these could be business columns like:

user_df = customers[['customer_id', 'name', 'email']]
Take Quiz

Real Codebase Usage

In real codebases, developers usually select columns in a few predictable ways.

1. Explicit column lists

This is the clearest and safest pattern:

df1 = df[['a', 'b']]

It is easy to read and avoids confusion.

2. .loc for row and column selection together

When filtering rows and selecting columns in one step:

active_users = users.loc[users['is_active'] == True, ['name', 'email']]

This pattern is very common.

3. Validation before selection

In production code, developers often check that columns exist:

required = ['a', 'b']
missing = [col for col in required if col not in df.columns]

if missing:
    raise KeyError(f"Missing columns: {missing}")

df1 = df[required]

4. Config-driven selection

Sometimes the list comes from settings or user input:

selected_columns = ['a', 'b']
df1 = df[selected_columns]

This makes pipelines flexible.

5. Method chaining

Column selection often appears in data-cleaning pipelines:

result = (
    df
    .dropna()
    .loc[:, ['a', 'b']]
    .rename(columns={'a': 'x', 'b': 'y'})
)

Common Mistakes

Here are some frequent beginner mistakes.

Mistake 1: Using a single bracket for multiple columns

Broken code:

df1 = df['a', 'b']

Why it fails:

  • Pandas does not interpret this as a list of columns.

Fix:

df1 = df[['a', 'b']]

Mistake 2: Confusing row slicing with column selection

Broken code:

df1 = df['a':'b']

Why it fails:

  • This is not the normal syntax for selecting columns by names from a to b.
  • In this form, slicing behavior applies differently and can be misleading.

Fix:

df1 = df.loc[:, 'a':'b']

Or use explicit names:

df1 = df[['a', 'b']]

Mistake 3: Using deprecated .ix

Broken code:

df1 = df.ix[:, 'a':'b']

Why it is a problem:

  • .ix has been removed from modern Pandas.
  • Old tutorials may still show it.

Fix:

df1 = df.loc[:, 'a':'b']

Mistake 4: Expecting a DataFrame but getting a Series

Code:

df1 = df['a']

Why it matters:

  • This returns a Series, not a DataFrame.
  • Some later code may fail if it expects 2D data.

Fix:

df1 = df[['a']]

Mistake 5: Selecting columns that do not exist

Broken code:

df1 = df[['a', 'd']]

Why it fails:

  • Column d is missing.

Fix:

print(df.columns)

Check available columns before selecting.

Comparisons

TaskSyntaxReturnsBest use
Select one columndf['a']SeriesWhen you need a single column as 1D data
Select one column as DataFramedf[['a']]DataFrameWhen later code expects a DataFrame
Select multiple columnsdf[['a', 'b']]DataFrameMost common and clearest approach
Select columns with .locdf.loc[:, ['a', 'b']]DataFrameGood when selecting rows and columns together
Select a column label rangedf.loc[:, 'a':'b']DataFrameUseful when columns are ordered and contiguous

df[['a', 'b']] vs df.loc[:, ['a', 'b']]

  • df[['a', 'b']]

    • Shorter
    • Very common
    • Best for simple column selection
  • df.loc[:, ['a', 'b']]

    • More explicit
    • Better when combined with row filtering

df['a'] vs df[['a']]

SyntaxOutput type
df['a']Series
df[['a']]DataFrame

This difference is small but very important in real code.

Take Quiz

Cheat Sheet

Quick reference

Select multiple columns

df1 = df[['a', 'b']]

Select all rows and chosen columns

df1 = df.loc[:, ['a', 'b']]

Select a column range by label

df1 = df.loc[:, 'a':'b']

Select one column as Series

s = df['a']

Select one column as DataFrame

df1 = df[['a']]

Rules to remember

  • One pair of brackets + one column name → Series
  • Two brackets + list of column names → DataFrame
  • Use .loc for explicit row/column label selection
  • Avoid .ix in modern Pandas

Common errors

df['a':'b']      # not the usual way to select columns
(df['a', 'b'])   # invalid for normal column selection

Safe pattern

columns = ['a', 'b']
df1 = df[columns]

FAQ

How do I select multiple columns in Pandas?

Use a list of column names inside double brackets:

df[['a', 'b']]

Why does df['a':'b'] not work for column selection?

Because that syntax is not the standard way to slice columns. It is interpreted differently and often relates to row slicing. Use df[['a', 'b']] or df.loc[:, 'a':'b'] instead.

What is the difference between df['a'] and df[['a']]?

df['a'] returns a Series. df[['a']] returns a DataFrame.

Is .ix still valid in Pandas?

No. .ix is deprecated and removed. Use .loc or .iloc instead.

How do I select a continuous range of columns by name?

Use .loc:

df.loc[:, 'a':'b']

How can I create a new DataFrame from selected columns?

Assign the result to a new variable:

df1 = df[['a', 'b']]

What happens if a column name is missing?

Pandas raises a KeyError. Check df.columns if needed.

Take Quiz

Mini Project

Description

Build a small data-cleaning script that extracts only the useful columns from a larger DataFrame. This mirrors a common real-world task where raw data contains extra fields, but your analysis or report only needs a few specific columns.

Goal

Create a new DataFrame containing only selected columns from an existing DataFrame and display the result.

Requirements

  • Create a Pandas DataFrame with at least four columns.
  • Select exactly two columns into a new DataFrame.
  • Print both the original DataFrame and the new DataFrame.
  • Use modern Pandas syntax only.
  • Include at least one example using .loc or double brackets.
Take Quiz

Keep learning

Related questions

View more