How do I create a new column where the values are selected based on an existing column?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Creating a new column from an existing column is one of the most common pandas tasks. The exact method depends on the rule: a simple two-way condition, a mapping table, or several branching conditions. In most cases, the best answer is a vectorized approach rather than a Python loop over rows.
Use np.where for a Simple Two-Way Rule
If the new column depends on one yes-or-no condition, numpy.where is compact and fast.
Output:
This is usually the cleanest solution when one condition determines one of two values.
Use np.select for Multiple Conditions
If there are several branching rules, np.select is often clearer than nesting multiple np.where calls.
This pattern scales better when the new column depends on more than one threshold or category branch.
Use map for Direct Value Translation
If each old value maps directly to a new value, a dictionary with Series.map is simpler than conditional logic.
This is ideal when the transformation is a lookup rather than a rule based on ranges or comparisons.
Use apply Only When the Logic Is Truly Custom
apply is flexible, but it is not the first choice for simple column logic. Use it when the transformation is too custom for vectorized operations.
This is readable, but it is usually slower than np.where, np.select, or map on large DataFrames.
Assign with .loc When Updating Only Certain Rows
Another common pattern is to set a default value first and then update selected rows with .loc.
This is very readable when the logic is mostly "default everything, then override some rows."
Why Vectorization Matters
A loop over DataFrame rows usually looks simple at first, but it is much slower and less idiomatic in pandas. Methods such as np.where, np.select, map, and boolean indexing operate on whole arrays and are typically easier to optimize and maintain.
That does not mean apply is forbidden. It just should not be the default answer for rules that already fit a built-in vectorized pattern.
Common Pitfalls
One common mistake is writing Python loops over rows for a problem that np.where or map could solve in one line. That hurts performance and often makes the code harder to read.
Another mistake is choosing map for range-based conditions. map is for direct value translation, not threshold logic.
Developers also sometimes forget about missing values. If a value is not in the mapping dictionary, map returns NaN unless you handle it explicitly.
Finally, chained assignment can create confusing warnings. If you are updating values conditionally, prefer assigning through .loc on the original DataFrame.
Summary
- Use
np.wherefor simple two-way conditions. - Use
np.selectfor multiple branching conditions. - Use
Series.mapfor direct old-value to new-value translation. - Use
.locwhen you want a default value plus targeted overrides. - Prefer vectorized pandas patterns over row-by-row loops whenever possible.

