To merge two columns in pandas, add them with + and a separator string. A sales team recently wanted one mailing-label column from separate city and state fields, and that one line did it.
It breaks when a ZIP code is an integer or a name is missing: you get a TypeError or a silent NaN.
Quick answer: add the columns with + and put a separator string between them. Convert non-text columns with astype(str) first:
df["location"] = df["city"] + ", " + df["state"]
In this tutorial, I’ll show you how to merge two columns pandas style on one customer table: text, numbers, missing values, three or more columns, and filling gaps.
How to Merge Two Text Columns in pandas with +
The running sample is four US customers, tested with Python 3.12.5 with pandas 3.0.6. For new-column basics, see my guide on adding a column to a pandas DataFrame covers the basics.
import pandas as pd
df = pd.DataFrame({
"first_name": ["Emily", "James", "Olivia", "Marcus"],
"last_name": ["Carter", "Nguyen", None, "Reed"],
"city": ["Austin", "Denver", "Boston", "Miami"],
"state": ["TX", "CO", "MA", "FL"],
"zip": [73301, 80202, 2134, 33101],
})
df["location"] = df["city"] + ", " + df["state"]
df["full_name"] = df["first_name"] + " " + df["last_name"]
print(df[["location", "full_name"]])
Output:
location full_name
0 Austin, TX Emily Carter
1 Denver, CO James Nguyen
2 Boston, MA NaN
3 Miami, FL Marcus Reed

NaN because her last name is missing.Merge a Text Column with a Number Column
pandas won’t add text to the integer zip column, so convert with astype(str). More conversions are in changing a column data type in pandas.
import pandas as pd
df = pd.DataFrame({
"first_name": ["Emily", "James", "Olivia", "Marcus"],
"last_name": ["Carter", "Nguyen", None, "Reed"],
"city": ["Austin", "Denver", "Boston", "Miami"],
"state": ["TX", "CO", "MA", "FL"],
"zip": [73301, 80202, 2134, 33101],
})
try:
df["state_zip"] = df["state"] + " " + df["zip"]
except TypeError as e:
print("TypeError:", str(e).splitlines()[0][:70])
df["state_zip"] = df["state"] + " " + df["zip"].astype(str).str.zfill(5)
print(df[["state", "zip", "state_zip"]])
Output:
TypeError: can only concatenate str (not "int") to str
state zip state_zip
0 TX 73301 TX 73301
1 CO 80202 CO 80202
2 MA 2134 MA 02134
3 FL 33101 FL 33101

+ raises a TypeError; after astype(str).str.zfill(5), Boston’s ZIP keeps its leading zero.How Do You Merge Columns with Missing Values?
Use Series.str.cat() with na_rep="" (missing becomes empty text), then str.strip() the leftover space:
import pandas as pd
df = pd.DataFrame({
"first_name": ["Emily", "James", "Olivia", "Marcus"],
"last_name": ["Carter", "Nguyen", None, "Reed"],
"city": ["Austin", "Denver", "Boston", "Miami"],
"state": ["TX", "CO", "MA", "FL"],
"zip": [73301, 80202, 2134, 33101],
})
df["full_name"] = df["first_name"].str.cat(df["last_name"], sep=" ", na_rep="")
df["full_name"] = df["full_name"].str.strip()
print(df[["first_name", "last_name", "full_name"]])
Output:
first_name last_name full_name
0 Emily Carter Emily Carter
1 James Nguyen James Nguyen
2 Olivia NaN Olivia
3 Marcus Reed Marcus Reed

Olivia instead of NaN, and the other three names are unchanged.Plain Python strings work differently; see concatenating strings in Python.
Merge Three or More Columns into One
agg(", ".join, axis=1) joins any number of string columns per row:
import pandas as pd
df = pd.DataFrame({
"first_name": ["Emily", "James", "Olivia", "Marcus"],
"last_name": ["Carter", "Nguyen", None, "Reed"],
"city": ["Austin", "Denver", "Boston", "Miami"],
"state": ["TX", "CO", "MA", "FL"],
"zip": [73301, 80202, 2134, 33101],
})
df["zip5"] = df["zip"].astype(str).str.zfill(5)
df["address"] = df[["city", "state", "zip5"]].agg(", ".join, axis=1)
print(df["address"].tolist())
Output:
['Austin, TX, 73301', 'Denver, CO, 80202', 'Boston, MA, 02134', 'Miami, FL, 33101']
To break a merged column apart again, see splitting a pandas column by a delimiter.
Fill One Column’s Gaps from Another with combine_first()
To keep the mobile number and fall back to the home number only when mobile is blank, use combine_first():
import pandas as pd
df = pd.DataFrame({
"name": ["Emily", "James", "Olivia", "Marcus"],
"mobile": ["512-555-0142", None, "617-555-0199", None],
"home": [None, "303-555-0117", "617-555-0100", None],
})
df["phone"] = df["mobile"].combine_first(df["home"])
print(df)
Output:
name mobile home phone
0 Emily 512-555-0142 NaN 512-555-0142
1 James NaN 303-555-0117 303-555-0117
2 Olivia 617-555-0199 617-555-0100 617-555-0199
3 Marcus NaN NaN NaN

Don’t confuse this with combining two tables. Joining DataFrames on a key is pandas merge and join, and stacking them is concatenating two DataFrames.
Common Errors When Merging pandas Columns
TypeErrorwith+: one column is numeric. Addastype(str).NaNin the result: a source value is missing. Usestr.cat(na_rep="")orfillna("").- ZIP like
2134.0: the column is float. Useastype("Int64")first.
When you’re cleaning up pandas columns, these walk-throughs come in handy:
- Replace values in a pandas column
- Set column names in pandas
- Get pandas column names
- Drop rows based on a column value
Frequently Asked Questions
How do I merge two columns in pandas?
Use df["a"] + " " + df["b"].
How do I combine a string column and an int column?
Convert the number first: df["a"] + df["n"].astype(str).
Why does merging columns give NaN?
+ returns NaN when either value is missing. Use str.cat(sep=" ", na_rep="").
How do I merge more than two columns?
Use df[["a", "b", "c"]].agg(", ".join, axis=1) on string columns.
Is pd.merge() used to merge two columns?
No. pd.merge() joins two DataFrames on keys. To combine columns inside one DataFrame, use + or str.cat().
Where is str.cat documented?
See Series.str.cat() in the pandas docs.

Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn