AlgoInsight

Q&A

How to create a new column with pandas

By AlgoInsight Team2026-06-07pandaspython

Overview

A pandas DataFrame is a 2-D table; columns are Series. Creating a new column is one of the most frequent data-wrangling tasks - deriving features, flags, or transformed values from existing data. Because pandas operations are vectorized, you usually compute an entire column at once without looping.

graph LR
    A[Existing DataFrame] --> B{New column source}
    B --> C[Constant scalar]
    B --> D[Computation on existing columns]
    B --> E[apply / map a function]
    B --> F[Conditional: np.where]
    C & D & E & F --> G[DataFrame with new column]
    style B fill:#1e1b4b,color:#fff

Setup

import pandas as pd
import numpy as np

df = pd.DataFrame({
    "name": ["Ada", "Linus", "Grace"],
    "price": [100, 250, 80],
    "qty": [2, 1, 5]
})

1. Assign a constant

df["currency"] = "USD"      # every row gets "USD"

2. Derive from existing columns (vectorized)

The most common case - arithmetic across columns happens elementwise:

df["total"] = df["price"] * df["qty"]   # 200, 250, 400

No loop needed; pandas applies the multiplication row by row in fast compiled code.

3. Assign a list or Series

df["region"] = ["EU", "EU", "US"]       # length must match number of rows

If you assign a Series, pandas aligns by index, not position - a subtle but important behavior.

4. Apply a function with .apply()

For row-wise logic that isn't a simple vectorized expression:

df["price_band"] = df["price"].apply(lambda p: "high" if p > 150 else "low")

# across multiple columns -> axis=1
df["summary"] = df.apply(lambda row: f"{row['name']}: {row['total']}", axis=1)

.apply() is flexible but slower than vectorized operations; prefer vectorization when possible.

5. Conditional columns with np.where

A fast, vectorized if/else:

df["expensive"] = np.where(df["price"] > 150, "yes", "no")

For multiple conditions, use np.select:

conditions = [df["price"] > 200, df["price"] > 100]
choices    = ["premium", "standard"]
df["tier"] = np.select(conditions, choices, default="budget")

6. The assign() method (chainable, non-mutating)

assign() returns a new DataFrame, which is ideal for method chaining and avoiding accidental mutation:

df2 = df.assign(
    total=df["price"] * df["qty"],
    with_tax=lambda d: d["total"] * 1.08   # can reference columns created earlier
)

7. Insert at a specific position with insert()

By default new columns go to the end; insert() places one at a chosen index:

df.insert(1, "sku", ["A1", "B2", "C3"])   # insert at column position 1

8. Using .loc[]

.loc can create a column too, and is the recommended way to set values conditionally without the "SettingWithCopyWarning":

df.loc[:, "in_stock"] = df["qty"] > 0
df.loc[df["price"] > 200, "flag"] = "review"   # only some rows; others become NaN

Mapping categorical values with .map()

region_names = {"EU": "Europe", "US": "United States"}
df["region_full"] = df["region"].map(region_names)

Why This Matters in Interviews

Data-engineering and analytics interviews love this because it reveals whether you think vectorized (fast, idiomatic) or loop-based (slow, un-Pythonic). Know the simple df['x'] = ... assignment, vectorized arithmetic, np.where/np.select for conditionals, and assign() for chaining. Explaining index alignment when assigning a Series is a strong detail.

Common Pitfalls

References

More answers