Pandas Merge Operation: What It Is and When to Use It
By
Community /
Developer
Nov 20, 2023
Navigate to:
In this post, you’ll learn how to merge different datasets or DataFrames using the pandas merge()
operation. We’ll take a closer look at the parameters of the merge()
function, what they mean, and how to use them. We’ll also understand how the merge()
function differs from pandas concat()
and join()
functions.
What Is Merge in Pandas?
The pandas library has a method called merge() for combining DataFrames or named Series into a singular DataFrame for better data analysis. The pandas merge operation combines two or more DataFrame objects based on columns or indexes in a similar fashion as join operations performed on databases. The goal is to have a new dataset while the sources remain unchanged.
A pandas merge can be performed using the pandas merge()
function or a DataFrame merge()
method.
Here’s the syntax for the pandas merge()
function:
pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, suffixes=('_x', '_y'))
The pd.merge()
function parameters are explained as follows:
- left: This indicates the DataFrame or named Series to be merged on the left.
- right: This indicates the DataFrame or named Series to be merged on the right.
- how: This defines the type of merge to be performed. The default is inner; others include outer, cross, left, and right.
- on: This specifies the column or index to join on. Both DataFrames must each have the same column for a join to happen; otherwise, an intersection of both columns is used.
- left_on: This specifies in the left DataFrame the column or index to join on.
- right_on: This specifies in the right DataFrame the column or index to join on.
- left_index: This uses the index of the left DataFrame for merging.
- right_index: This uses the index of the right DataFrame for merging.
- suffixes: This outlines the suffixes to be used on overlapping column names in the left and right DataFrames.
Let’s see how we can perform a pandas merge on two DataFrames.
Inner Join
One way of merging DataFrames with the merge()
function is by using the inner
join. The inner
join always returns matching rows from DataFrames based on the column being used as the key for the merge. An inner
join is done by default when you don’t specify how the merge should be done using the how
parameter.
Let’s see an example:
import pandas as pd
alderman_data = {
'ward': [1, 3, 4, 5, 6],
'alderman': ['Vicky Mintoff', 'Petrina Finney', 'Kennith Gossop', 'Northrup Jaquet', 'Kelby Thaxton'],
'address': ['7 Eggendart Pass', '2 Aberg Circle', '9 Barnett Way', '3 Anhalt Street', '86 Drewry Drive'],
'phone': ['773-450-9926', '312-915-4064', '312-144-7339', '309-237-8875', '309-486-6591'],
'state': ['Illinois', 'Illinois', 'Illinois', 'Illinois', 'Illinois']
}
alderman_df = pd.DataFrame(alderman_data)
population_data = {
'ward': [1, 2, 3, 5, 7],
'pop_2015': [25112, 27557, 27043, 26360, 27467],
'pop_2020': [36778, 43417, 54184, 37978, 55985],
'pop_change': [11666, 15860, 27141, 11618, 28518],
'city': ['Chicago', 'Peoria', 'Chicago', 'Chicago', 'Springfield'],
'state': ['Illinois', 'Illinois', 'Illinois', 'Illinois', 'Illinois'],
'zip': [60691, 61635, 60604, 60614, 62794]
}
population_df = pd.DataFrame(population_data)
print(alderman_df)
print()
print(population_df)
Here’s the output of the above code:
Alderman DataFrame:
ward alderman address phone state
0 1 Vicky Mintoff 7 Eggendart Pass 773-450-9926 Illinois
1 3 Petrina Finney 2 Aberg Circle 312-915-4064 Illinois
2 4 Kennith Gossop 9 Barnett Way 312-144-7339 Illinois
3 5 Northrup Jaquet 3 Anhalt Street 309-237-8875 Illinois
4 6 Kelby Thaxton 86 Drewry Drive 309-486-6591 Illinois
Ward Population DataFrame:
ward pop_2015 pop_2020 pop_change city state zip
0 1 25112 36778 11666 Chicago Illinois 60691
1 2 27557 43417 15860 Peoria Illinois 61635
2 3 27043 54184 27141 Chicago Illinois 60604
3 5 26360 37978 11618 Chicago Illinois 60614
4 7 27467 55985 28518 Springfield Illinois 62794;
Let’s merge the alderman_df and population_df and see the result.
merged_df = pd.merge(alderman_df, population_df, on="ward")
print(merged_df.head())
Here’s the output of the above code:
ward alderman address phone state_x pop_2015
0 1 Vicky Mintoff 7 Eggendart Pass 773-450-9926 Illinois 25112 \
1 3 Petrina Finney 2 Aberg Circle 312-915-4064 Illinois 27043
2 5 Northrup Jaquet 3 Anhalt Street 309-237-8875 Illinois 26360
pop_2020 pop_change city state_y zip
0 36778 11666 Chicago Illinois 60691
1 54184 27141 Chicago Illinois 60604
2 37978 11618 Chicago Illinois 60614
As can be seen from the above code, we performed a merge of two DataFrames — alderman_df and population_df — on the ward column that’s present in both. By default, the new DataFrame has _x and _y suffixes appended to the state columns because they have similarly named columns in the source datasets. However, you can define proper suffixes for your new DataFrame for any overlapping columns. When performing an inner join, rows with matching values in both DataFrames would be returned. In this case, rows 1, 3, and 5 are returned because the ward columns in the original DataFrames being merged have matching values.
Left Join
Another way to merge DataFrames or named Series is by specifying a left join using the how parameter. The left join returns all rows from the left DataFrame and rows on the right DataFrame where the key column(s) match.
We’ll still use the alderman_df and population_df for this example:
left_merge_df = pd.merge(alderman_df, population_df, on='ward', how='left')
print(left_merged_df)
Here’s the output of the above code:
ward alderman address phone state_x pop_2015
0 1 Vicky Mintoff 7 Eggendart Pass 773-450-9926 Illinois 25112.0 \
1 3 Petrina Finney 2 Aberg Circle 312-915-4064 Illinois 27043.0
2 4 Kennith Gossop 9 Barnett Way 312-144-7339 Illinois NaN
3 5 Northrup Jaquet 3 Anhalt Street 309-237-8875 Illinois 26360.0
4 6 Kelby Thaxton 86 Drewry Drive 309-486-6591 Illinois NaN
pop_2020 pop_change city state_y zip
0 36778.0 11666.0 Chicago Illinois 60691.0
1 54184.0 27141.0 Chicago Illinois 60604.0
2 NaN NaN NaN NaN NaN
3 37978.0 11618.0 Chicago Illinois 60614.0
4 NaN NaN NaN NaN NaN
The result of the left join shows that all rows of data from the left DataFrame alderman_df are returned. However, missing values are indicated with NaN for population_df without matching column keys.
Right Join
Performing the right join on two DataFrames is just as easy as we did with the left join. Simply specify right as the value for the how parameter. All rows on the right DataFrame are returned and rows on the left DataFrame that match the key column(s) are returned as well.
right_merge_df = pd.merge(alderman_df, population_df, on='ward', how='right')
print(right_merge_df)
Here’s the output of the above code:
ward alderman address phone state_x pop_2015
0 1 Vicky Mintoff 7 Eggendart Pass 773-450-9926 Illinois 25112 \
1 2 NaN NaN NaN NaN 27557
2 3 Petrina Finney 2 Aberg Circle 312-915-4064 Illinois 27043
3 5 Northrup Jaquet 3 Anhalt Street 309-237-8875 Illinois 26360
4 7 NaN NaN NaN NaN 27467
pop_2020 pop_change city state_y zip
0 36778 11666 Chicago Illinois 60691
1 43417 15860 Peoria Illinois 61635
2 54184 27141 Chicago Illinois 60604
3 37978 11618 Chicago Illinois 60614
4 55985 28518 Springfield Illinois 62794
Outer Join
Besides the inner, left, and right joins, there’s the outer join. The outer join returns all rows from both datasets whether there’s a match in the key column or not. In essence, the outer join will return all rows from merged datasets, with non-matching rows having NaN to indicate missing values. We’ll see the result of an outer join using the alderman_df and population_df DataFrames.
outer_merge_df = pd.merge(alderman_df, population_df, on='ward', how='outer')
print(outer_merge_df)
Here’s the output of the above code:
ward alderman address phone state_x pop_2015
0 1 Vicky Mintoff 7 Eggendart Pass 773-450-9926 Illinois 25112.0 \
1 3 Petrina Finney 2 Aberg Circle 312-915-4064 Illinois 27043.0
2 4 Kennith Gossop 9 Barnett Way 312-144-7339 Illinois NaN
3 5 Northrup Jaquet 3 Anhalt Street 309-237-8875 Illinois 26360.0
4 6 Kelby Thaxton 86 Drewry Drive 309-486-6591 Illinois NaN
5 2 NaN NaN NaN NaN 27557.0
6 7 NaN NaN NaN NaN 27467.0
pop_2020 pop_change city state_y zip
0 36778.0 11666.0 Chicago Illinois 60691.0
1 54184.0 27141.0 Chicago Illinois 60604.0
2 NaN NaN NaN NaN NaN
3 37978.0 11618.0 Chicago Illinois 60614.0
4 NaN NaN NaN NaN NaN
5 43417.0 15860.0 Peoria Illinois 61635.0
6 55985.0 28518.0 Springfield Illinois 62794.0
From the above code snippet, the outer join returned seven rows of data to accommodate all rows from alderman_df and population_df. The two datasets merged in the outer join each had five rows of data.
How to Merge DataFrames on Indexes
Datasets can be merged based on their indexes by providing arguments for the left_on and right_on or left_index and right_index parameters. There are a few rules to observe when using any other aforementioned parameters:
- You can only pass the argument left_on or left_index, not both.
- You can only pass the argument right_on or right_index, not both.
- You can only pass the argument on or left_on and right_on, not a combination of both.
- You can only pass the argument on or left_index and right_index, not a combination of both.
With the left_on and right_on parameters, you pass arguments to indicate columns to be used for merging on the left and on the right respectively. For the left_index and right_index parameters, you set the arguments to True for both.
Let’s see an example:
index_merge_df = pd.merge(alderman_df, population_df, left_index=True, right_index=True)
print(index_merge_df)
Here’s the output of the above code:
ward_x alderman address phone state_x ward_y
0 1 Vicky Mintoff 7 Eggendart Pass 773-450-9926 Illinois 1 \
1 3 Petrina Finney 2 Aberg Circle 312-915-4064 Illinois 2
2 4 Kennith Gossop 9 Barnett Way 312-144-7339 Illinois 3
3 5 Northrup Jaquet 3 Anhalt Street 309-237-8875 Illinois 5
4 6 Kelby Thaxton 86 Drewry Drive 309-486-6591 Illinois 7
pop_2015 pop_2020 pop_change city state_y zip
0 25112 36778 11666 Chicago Illinois 60691
1 27557 43417 15860 Peoria Illinois 61635
2 27043 54184 27141 Chicago Illinois 60604
3 26360 37978 11618 Chicago Illinois 60614
4 27467 55985 28518 Springfield Illinois 62794
From the output of our code, the merge
function uses the ward column of each dataset for the left and right index. All rows from both datasets were returned, and matching values weren’t considered on the left or right index. Therefore, we have five rows in the new dataset.
Difference Between Merge and Concat
What’s the difference between concat and merge? The pandas concat()
function is used to combine DataFrames or named Series vertically or horizontally. By default, the concat()
function joins DataFrames vertically. Alternatively, setting the axis parameter argument to 1 gives a horizontal merge. Unlike the merge()
function, only outer or inner joins can be performed on DataFrames when concatenating.
Here’s the syntax for the pandas concat()
function:
pandas.concat(objs, *, axis=0, join='outer', ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, sort=False, copy=None)
Let’s see an example:
alderman_data2 = {
'ward': [9, 10, 11, 12, 13],
'alderman': ['Vicky Griffin', 'Blake Finney', 'Greg Theodore', 'Jacqueline Bob', 'Shelby Boston'],
'address': ['7 Haas Circle', '2 Mayer Lane', '9 Harper Drive', '3 Grover Avenue', '86 Palm Drive'],
'phone': ['312-978-5864', '217-352-4548', '312-568-4492', '815-254-3682', '309-590-9629'],
'state': ['Illinois', 'Illinois', 'Illinois', 'Illinois', 'Illinois']
}
alderman_df2 = pd.DataFrame(alderman_data2)
concat_df = pd.concat([alderman_df, alderman_df2])
print(concat_df)
Here’s the output of the above code:
ward alderman address phone state
0 1 Vicky Mintoff 7 Eggendart Pass 773-450-9926 Illinois
1 3 Petrina Finney 2 Aberg Circle 312-915-4064 Illinois
2 4 Kennith Gossop 9 Barnett Way 312-144-7339 Illinois
3 5 Northrup Jaquet 3 Anhalt Street 309-237-8875 Illinois
4 6 Kelby Thaxton 86 Drewry Drive 309-486-6591 Illinois
0 9 Vicky Griffin 7 Haas Circle 312-978-5864 Illinois
1 10 Blake Finney 2 Mayer Lane 217-352-4548 Illinois
2 11 Greg Theodore 9 Harper Drive 312-568-4492 Illinois
3 12 Jacqueline Bob 3 Grover Avenue 815-254-3682 Illinois
4 13 Shelby Boston 86 Palm Drive 309-590-9629 Illinois
Two DataFrame objects alderman_df and alderman_df2 are combined vertically using the concat()
function. The two datasets combined still retain their original indexes; however, this can be overridden by setting the ignore_index parameter argument to True.
A common use case for the pandas concat()
function is to stack similar data obtained at different points vertically. In the example above, a second part of the Alderman list was added to the previous one to elongate the list. It can also be used to give data a hierarchical index.
Difference Between Pandas Merge and Join methods
Besides the merge()
and concat()
functions, pandas provides the DataFrame join()
method for combining different datasets into a new one. The join()
method is similar to the merge()
function in terms of parameters and operations. But the biggest difference between the two is that join combines DataFrames based on index while merge combines with both indexes or columns. By default, the join()
method performs a left join while the merge does an inner join.
A join()
method syntax looks like this:
DataFrame.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False, validate=None)
Here’s an example:
joined_df = alderman_df.join(population_df, on='ward', lsuffix='_x', rsuffix='_y')
print(joined_df)
Here’s the output of the above code:
ward_x alderman address phone state_x ward_y
0 1 Vicky Mintoff 7 Eggendart Pass 773-450-9926 Illinois 2.0 \
1 3 Petrina Finney 2 Aberg Circle 312-915-4064 Illinois 5.0
2 4 Kennith Gossop 9 Barnett Way 312-144-7339 Illinois 7.0
3 5 Northrup Jaquet 3 Anhalt Street 309-237-8875 Illinois NaN
4 6 Kelby Thaxton 86 Drewry Drive 309-486-6591 Illinois NaN
pop_2015 pop_2020 pop_change city state_y zip
0 27557.0 43417.0 15860.0 Peoria Illinois 61635.0
1 26360.0 37978.0 11618.0 Chicago Illinois 60614.0
2 27467.0 55985.0 28518.0 Springfield Illinois 62794.0
3 NaN NaN NaN NaN NaN NaN
4 NaN NaN NaN NaN NaN NaN
Notice an inner join is performed because all rows of data from the alderman_df are returned, while rows with missing data are indicated with NaN where the index doesn’t match with the right DataFrame population_df.
Wrapping up
In summary, the pandas merge()
operation is the most flexible means of combining datasets. It gives you the option of joining DataFrames based on indexes or columns. The function also performs different types of joins: inner, outer, left, right, and cross. It’s often the most-used method or function for combining datasets in pandas. What’s the alternative to merge in pandas? In general, the concat()
and join()
methods are alternatives for pandas merge.
The concat()
function is ideal when stacking a series of DataFrames vertically. Furthermore, it’s used to join data tables horizontally and limited to inner to outer joins.
The join()
method is straightforward and often used when you need to combine datasets along the indexes. It performs a left join by default as well as outer, inner, and right.
Depending on your need, you can pick any of these methods to combine your datasets before making an analysis.
This post was written by Iniubong Arthur. Iniubong is a software developer and a technical writer with 2+ industry experience. He writes Python, Java, JavaScript, and has also used Django and React for building projects.