HOWTO · Pandas

How to Merge Two Pandas Series Into a DataFrame

This guide demonstrates how to combine or merge two Pandas series into a DataFrame using pandas.concat(), pandas.merge(), DataFrame.join() methods.

On this page

In pandas, a Series is a one-dimensional labeled array — roughly a single column of data with an index. To merge two or more Series into a DataFrame, pass them to pandas.concat() with axis=1; each Series becomes a column headed by its name. When you need different semantics, pandas.concat() can also stack Series vertically, pandas.merge() matches rows by index like a SQL join, and DataFrame.join() attaches a named Series to an existing DataFrame.

This tutorial walks through each approach with runnable examples.

Choose a method based on the result you need

All four approaches produce tabular data, but they answer different questions:

  • pandas.concat([s1, s2], axis=1) places the Series side by side so each one becomes a column of a new DataFrame.
  • pandas.concat([s1, s2]) with the default axis=0 stacks the Series into a single longer Series; wrap the result in pd.DataFrame() for a one-column DataFrame. This is the current replacement for Series.append(), which was removed in pandas 2.0.
  • pandas.merge(left, right, left_index=True, right_index=True) matches rows by index, or by shared key values, the way a SQL join does.
  • df.join(series) adds a named Series to a DataFrame you already have, aligning on the index.

One behavior ties these together: pandas aligns labeled data by index. When the input Series share the same index, alignment is invisible. When indexes differ, the labels present in only one input produce missing values (NaN) in the combined result.

Combine Series as columns with pandas.concat()

The pandas.concat() function concatenates pandas objects along an axis. Passing axis=1 lines the objects up as columns; each Series name becomes a column header and rows are aligned on the index.

Run this example:

import pandas as pd

# Create Series by assigning names
products = pd.Series(
    ["Intel Dell Laptops", "HP Laptops", "Lenavo Laptops", "Acer Laptops"],
    name="Products",
)
dollar_price = pd.Series([350, 300, 400, 250], name="Price")
percentage_sale = pd.Series([83, 99, 84, 76], name="Sale")

# merge three pandas series as columns using pandas.concat()
df = pd.concat([products, dollar_price, percentage_sale], axis=1)
print(df)

Output:

             Products  Price  Sale
0  Intel Dell Laptops    350    83
1          HP Laptops    300    99
2      Lenavo Laptops    400    84
3        Acer Laptops    250    76

Because the three Series share the default integer index, the rows line up in order. With axis=0 (the default) the same call would stack the values into one long Series instead of building columns.

Stack Series vertically with pandas.concat()

Older versions of this task used Series.append(), a shortcut that concatenated along axis=0. That method was deprecated in pandas 1.4 and removed in pandas 2.0, so calling it now produces an AttributeError. The replacement is pandas.concat(): pass the Series in a list and set ignore_index=True to renumber the combined result.

import pandas as pd

technical = pd.Series(["Pandas", "Python", "Scala", "Hadoop"])
non_technical = pd.Series(["SEO", "Graphic design", "Content writing", "Marketing"])

# stack the series and shape the result into a one-column DataFrame
df = pd.DataFrame(
    pd.concat([technical, non_technical], ignore_index=True), columns=["Skills"]
)
print(df)

Output:

            Skills
0           Pandas
1           Python
2            Scala
3           Hadoop
4              SEO
5   Graphic design
6  Content writing
7        Marketing

Here pd.concat() returns a single Series of eight values, and pd.DataFrame(..., columns=["Skills"]) shapes it into a one-column DataFrame. To keep the original index labels instead of renumbering, drop ignore_index=True.

Match Series by index with pandas.merge()

pandas.merge() performs SQL-style joins between named Series or DataFrame objects. Because the merged values become columns, each Series needs a name. Setting left_index=True and right_index=True tells pandas.merge() to match rows on the index rather than on a key column.

import pandas as pd

# Create Series by assigning names
products = pd.Series(
    ["Intel Dell Laptops", "HP Laptops", "Lenavo Laptops", "Acer Laptops"],
    name="Products",
)
dollar_price = pd.Series([350, 300, 400, 250], name="Price")

# match the two series on their index labels
df = pd.merge(products, dollar_price, right_index=True, left_index=True)
print(df)

Output:

             Products  Price
0  Intel Dell Laptops    350
1          HP Laptops    300
2      Lenavo Laptops    400
3        Acer Laptops    250

The default join is how="inner", so index labels present in only one Series are left out of the result; pass how="outer" to keep every label and fill the gaps with NaN. To match on values instead of the index, convert the Series to DataFrames and pass a column name to on.

Join a Series to a DataFrame with DataFrame.join()

DataFrame.join() is the most convenient option when one side is already a DataFrame. Convert the first Series with pd.DataFrame(), then call .join() with the second Series; the Series must have a name, which becomes the new column header.

import pandas as pd

# Create Series by assigning names
products = pd.Series(
    ["Intel Dell Laptops", "HP Laptops", "Lenavo Laptops", "Acer Laptops"],
    name="Products",
)
dollar_price = pd.Series([350, 300, 400, 250], name="Price")

# join the price series to a DataFrame built from products
df = pd.DataFrame(products).join(dollar_price)
print(df)

Output:

             Products  Price
0  Intel Dell Laptops    350
1          HP Laptops    300
2      Lenavo Laptops    400
3        Acer Laptops    250

Like pandas.merge(), DataFrame.join() aligns on the index, but it defaults to a left join so every row of the calling DataFrame is kept.

To recap the method choice: reach for pandas.concat() with axis=1 to build a DataFrame from independent Series, use pandas.concat() along axis=0 for the stacking task Series.append() used to perform, use pandas.merge() when rows must be matched by index or key values, and use DataFrame.join() to attach a named Series to a DataFrame you already have.