Python

How to unnest explode a column in a pandas DataFrame into multiple rows

27 September 2026 · 13 min read

How to unnest explode a column in a pandas DataFrame into multiple rows

Working with data often involves dealing with nested structures within columns of a Pandas DataFrame. A common task is learning how to unnest (explode) a column in a Pandas DataFrame, which transforms a single row containing a list-like or array-like value into multiple rows, each corresponding to an item in that list. This operation is crucial for data analysis, preprocessing, and preparing data for machine learning models. Exploding a column effectively flattens the DataFrame, making it easier to perform aggregations, filtering, and other data manipulations. For instance, imagine you have a DataFrame where one column lists the products purchased by each customer; unnesting this column will create a new row for each product purchased by each customer, providing a detailed transactional view of the data. Understanding this process is essential for any data scientist or analyst using Python and Pandas.

Understanding the Basics of Unnesting (Exploding) in Pandas

The core concept behind unnesting, often referred to as “exploding” in Pandas terminology, is to duplicate rows based on the elements within a list-like or array-like column. This action transforms a single row with a list into multiple rows, where each new row contains a single element from the original list. This is extremely useful when you’re dealing with data that has been aggregated or structured in a way that doesn’t fit the desired analysis format. For example, consider a DataFrame containing information about movies, where one column lists the genres associated with each movie. Unnesting this genre column would create separate rows for each movie-genre combination, enabling you to analyze movie trends by genre more effectively.

Pandas provides a straightforward method for achieving this: the explode() function. This function takes a column name as input and returns a new DataFrame where each element of the list-like column is expanded into its own row. It’s important to note that the other columns in the DataFrame remain unchanged, simply duplicated across the new rows. According to the Pandas documentation [Pandas explode documentation], the explode() function handles missing values (NaN) gracefully, either skipping them or converting them to individual rows with NaN values, depending on the specific use case. This behavior ensures data integrity during the unnesting process.

Before using explode(), it’s crucial to ensure that the column you intend to unnest contains list-like or array-like data. Applying explode() to a column containing scalar values (e.g., integers, strings) will result in an error. Data cleaning and preprocessing might be necessary to transform the column into the correct format before unnesting. For example, if your column contains comma-separated strings instead of lists, you would first need to split the strings into lists using the str.split() method before applying explode(). Proper data preparation is key to a successful unnesting operation.

Step-by-Step Guide to Exploding a Column

Unnesting a column in Pandas is a relatively simple process, but it requires careful attention to data types and potential edge cases. This section provides a step-by-step guide to effectively explode a column in your DataFrame:

  1. Import the Pandas library: Begin by importing the Pandas library, which is essential for working with DataFrames in Python. Use the statement import pandas as pd.
  2. Create or load your DataFrame: Create a DataFrame, or load data from a file (e.g., CSV, Excel) into a DataFrame. Make sure the DataFrame contains the column you want to unnest.
  3. Inspect the column to be unnested: Before applying explode(), inspect the column to confirm that it contains list-like or array-like data. Use df[‘column_name’].head() to view the first few rows of the column.
  4. Apply the explode() function: Use the explode() function to unnest the column. The syntax is df = df.explode(‘column_name’), where ‘column_name’ is the name of the column you want to unnest. The result is a new DataFrame with the column exploded.
  5. Verify the results: After applying explode(), verify that the column has been correctly unnested by examining the DataFrame. Use df.head() to view the first few rows of the modified DataFrame.

Let’s illustrate this process with an example. Suppose you have a DataFrame named customer_data with a column named products_purchased containing a list of products purchased by each customer. To unnest this column, you would use the following code: customer_data = customer_data.explode(‘products_purchased’). This will create a new row for each product purchased by each customer, effectively transforming the DataFrame from a customer-centric view to a product-transaction view.

Handling missing values is also important. If your list column contains NaN values, explode() will treat them as empty lists and create a new row with NaN in the exploded column and the other columns remaining the same. If you want to drop these rows, you can use df.dropna(subset=[‘column_name’]) after applying explode(). This will remove any rows where the exploded column contains NaN values, ensuring a clean and consistent DataFrame.

Advanced Techniques and Considerations

While the basic explode() function is sufficient for simple unnesting tasks, more complex scenarios may require advanced techniques. One common scenario involves unnesting multiple columns simultaneously. This can be achieved by chaining the explode() function multiple times, applying it to each column sequentially. However, it’s essential to consider the order in which you unnest the columns, as this can affect the final structure of the DataFrame. For example, unnesting column A before column B will result in a different DataFrame than unnesting column B before column A if the lists in the columns are of different lengths. According to a Stack Overflow discussion [Pandas Explode Discussion], using itertools.product combined with explode can provide a more controlled approach when dealing with multiple columns.

Another important consideration is the performance of the explode() function, especially when dealing with large DataFrames. Unnesting a column can significantly increase the number of rows in the DataFrame, which can impact memory usage and processing time. To improve performance, consider optimizing the data types of the columns before applying explode(). For example, converting a column containing strings to a category type can reduce memory consumption. Additionally, using vectorized operations instead of iterating through the rows can also improve performance. The Pandas documentation [Pandas Official Documentation] provides detailed information on optimizing Pandas code for performance.

Sometimes, you might want to retain the original list structure in a separate column after unnesting. This can be useful for tracking the origin of each element in the exploded column. To achieve this, create a copy of the list column before applying explode(), and then use the original column as a reference. For instance, you could create a new column named original_list by assigning df[‘original_list’] = df[‘column_name’].copy() before exploding column_name. This will allow you to trace back the original list from which each element in the exploded column originated.

Real-World Examples and Use Cases

The ability to unnest a column in Pandas is invaluable in various real-world scenarios. Consider an e-commerce platform where each order can contain multiple products. The order data might be stored in a DataFrame with one column listing the products included in each order. Unnesting this column allows you to analyze product sales per order, calculate average order value, and identify popular product combinations. This provides valuable insights for optimizing product placement, marketing campaigns, and inventory management.

Another common use case is in social media analysis. Suppose you have a DataFrame containing information about social media posts, and one column lists the hashtags used in each post. By unnesting the hashtag column, you can analyze the frequency of each hashtag, identify trending topics, and understand the relationships between different hashtags. This information can be used to improve content strategy, target specific audiences, and track the performance of social media campaigns. According to a study by HubSpot, analyzing hashtag usage can significantly improve social media engagement rates [HubSpot Social Media Trends].

Infographic here: Visualizing the Unnesting Process
Furthermore, unnesting can be applied in scientific research. For example, in genomics, you might have a DataFrame containing information about genes and their associated pathways. Unnesting the pathway column allows you to analyze the frequency of each pathway, identify genes involved in multiple pathways, and understand the relationships between different genes and pathways. This can provide valuable insights into gene function, disease mechanisms, and potential drug targets. These scenarios underscore the versatility and importance of unnesting in data analysis.
  • Improved data granularity for analysis.
  • Facilitates aggregation and filtering operations.
  • Enables detailed insights into relationships within data.

FAQ: Common Questions About Unnesting in Pandas

**What happens if I try to explode a column that doesn't contain lists?**
If you try to explode() a column containing scalar values (e.g., integers, strings), Pandas will raise a TypeError. Ensure your column contains lists or array-like data before using explode(). You might need to preprocess your data to convert it into the correct format first.
**How does explode() handle missing values (NaN)?**
When the column to be exploded contains NaN values, explode() treats them as empty lists. This results in a row with the NaN value being transformed into a single row where the exploded column also contains NaN. You can use dropna() to remove these rows if needed.
**Can I unnest multiple columns at once?**
Yes, you can unnest multiple columns by chaining the explode() function multiple times. However, the order in which you unnest the columns matters, as it can affect the final structure of the DataFrame. Consider the dependencies between the columns before unnesting them.
**Is there a performance impact when using explode() on large DataFrames?**
Yes, explode() can significantly increase the number of rows in the DataFrame, which can impact memory usage and processing time. Optimize data types and use vectorized operations to improve performance. Consider using chunking or other memory management techniques for extremely large DataFrames.
- Always check data types before exploding. - Handle missing values appropriately. - Consider performance implications for large datasets.

By mastering the explode() function, you’ll find yourself better equipped to tackle complex data manipulation tasks and extract meaningful insights from your datasets. This skill unlocks the ability to transform aggregated data into a more granular format, enabling deeper analysis and informed decision-making. Remember to always validate your results and handle edge cases carefully to ensure the integrity of your data. For further exploration, consider delving into Pandas’ other powerful data manipulation functions, such as groupby(), pivot_table(), and merge(). These tools, combined with the ability to unnest data, will significantly enhance your data analysis capabilities. Ready to put your newfound knowledge into practice? Start experimenting with your own DataFrames and discover the power of unnesting!

Question & Answer :
I have the following DataFrame where one of the columns is an object (list type cell):

df = pd.DataFrame({'A': [1, 2], 'B': [[1, 2], [1, 2]]}) 

Output:

A B 0 1 [1, 2] 1 2 [1, 2] 

My expected output is:

A B 0 1 1 1 1 2 3 2 1 4 2 2 

What should I do to achieve this?


Related question

Pandas column of lists, create a row for each list element

Good question and answer but only handle one column with list(In my answer the self-def function will work for multiple columns, also the accepted answer is use the most time consuming apply , which is not recommended, check more info When should I (not) want to use pandas apply() in my code?)

I know object dtype columns makes the data hard to convert with pandas functions. When I receive data like this, the first thing that came to mind was to “flatten” or unnest the columns.

I am using pandas and Python functions for this type of question. If you are worried about the speed of the above solutions, check out user3483203’s answer, since it’s using numpy and most of the time numpy is faster. I recommend Cython or numba if speed matters.


Method 0 [pandas >= 0.25] Starting from pandas 0.25, if you only need to explode one column, you can use the pandas.DataFrame.explode function:

df.explode('B') A B 0 1 1 1 1 2 0 2 1 1 2 2 

Given a dataframe with an empty list or a NaN in the column. An empty list will not cause an issue, but a NaN will need to be filled with a list

df = pd.DataFrame({'A': [1, 2, 3, 4],'B': [[1, 2], [1, 2], [], np.nan]}) df.B = df.B.fillna({i: [] for i in df.index}) # replace NaN with [] df.explode('B') A B 0 1 1 0 1 2 1 2 1 1 2 2 2 3 NaN 3 4 NaN 

Method 1 apply + pd.Series (easy to understand but in terms of performance not recommended . )

df.set_index('A').B.apply(pd.Series).stack().reset_index(level=0).rename(columns={0:'B'}) Out[463]: A B 0 1 1 1 1 2 0 2 1 1 2 2 

Method 2 Using repeat with DataFrame constructor , re-create your dataframe (good at performance, not good at multiple columns )

df=pd.DataFrame({'A':df.A.repeat(df.B.str.len()),'B':np.concatenate(df.B.values)}) df Out[465]: A B 0 1 1 0 1 2 1 2 1 1 2 2 

Method 2.1 for example besides A we have A.1 …..A.n. If we still use the method(Method 2) above it is hard for us to re-create the columns one by one .

Solution : join or merge with the index after ‘unnest’ the single columns

s=pd.DataFrame({'B':np.concatenate(df.B.values)},index=df.index.repeat(df.B.str.len())) s.join(df.drop('B',1),how='left') Out[477]: B A 0 1 1 0 2 1 1 1 2 1 2 2 

If you need the column order exactly the same as before, add reindex at the end.

s.join(df.drop('B',1),how='left').reindex(columns=df.columns) 

Method 3 recreate the list

pd.DataFrame([[x] + [z] for x, y in df.values for z in y],columns=df.columns) Out[488]: A B 0 1 1 1 1 2 2 2 1 3 2 2 

If more than two columns, use

s=pd.DataFrame([[x] + [z] for x, y in zip(df.index,df.B) for z in y]) s.merge(df,left_on=0,right_index=True) Out[491]: 0 1 A B 0 0 1 1 [1, 2] 1 0 2 1 [1, 2] 2 1 1 2 [1, 2] 3 1 2 2 [1, 2] 

Method 4 using reindex or loc

df.reindex(df.index.repeat(df.B.str.len())).assign(B=np.concatenate(df.B.values)) Out[554]: A B 0 1 1 0 1 2 1 2 1 1 2 2 #df.loc[df.index.repeat(df.B.str.len())].assign(B=np.concatenate(df.B.values)) 

Method 5 when the list only contains unique values:

df=pd.DataFrame({'A':[1,2],'B':[[1,2],[3,4]]}) from collections import ChainMap d = dict(ChainMap(*map(dict.fromkeys, df['B'], df['A']))) pd.DataFrame(list(d.items()),columns=df.columns[::-1]) Out[574]: B A 0 1 1 1 2 1 2 3 2 3 4 2 

Method 6 using numpy for high performance:

newvalues=np.dstack((np.repeat(df.A.values,list(map(len,df.B.values))),np.concatenate(df.B.values))) pd.DataFrame(data=newvalues[0],columns=df.columns) A B 0 1 1 1 1 2 2 2 1 3 2 2 

Method 7 using base function itertools cycle and chain: Pure python solution just for fun

from itertools import cycle,chain l=df.values.tolist() l1=[list(zip([x[0]], cycle(x[1])) if len([x[0]]) > len(x[1]) else list(zip(cycle([x[0]]), x[1]))) for x in l] pd.DataFrame(list(chain.from_iterable(l1)),columns=df.columns) A B 0 1 1 1 1 2 2 2 1 3 2 2 

Generalizing to multiple columns

df=pd.DataFrame({'A':[1,2],'B':[[1,2],[3,4]],'C':[[1,2],[3,4]]}) df Out[592]: A B C 0 1 [1, 2] [1, 2] 1 2 [3, 4] [3, 4] 

Self-def function:

def unnesting(df, explode): idx = df.index.repeat(df[explode[0]].str.len()) df1 = pd.concat([ pd.DataFrame({x: np.concatenate(df[x].values)}) for x in explode], axis=1) df1.index = idx return df1.join(df.drop(explode, 1), how='left') unnesting(df,['B','C']) Out[609]: B C A 0 1 1 1 0 2 2 1 1 3 3 2 1 4 4 2 

Column-wise Unnesting

All above method is talking about the vertical unnesting and explode , If you do need expend the list horizontal, Check with pd.DataFrame constructor

df.join(pd.DataFrame(df.B.tolist(),index=df.index).add_prefix('B_')) Out[33]: A B C B_0 B_1 0 1 [1, 2] [1, 2] 1 2 1 2 [3, 4] [3, 4] 3 4 

Updated function

def unnesting(df, explode, axis): if axis==1: idx = df.index.repeat(df[explode[0]].str.len()) df1 = pd.concat([ pd.DataFrame({x: np.concatenate(df[x].values)}) for x in explode], axis=1) df1.index = idx return df1.join(df.drop(explode, 1), how='left') else : df1 = pd.concat([ pd.DataFrame(df[x].tolist(), index=df.index).add_prefix(x) for x in explode], axis=1) return df1.join(df.drop(explode, 1), how='left') 

Test Output

unnesting(df, ['B','C'], axis=0) Out[36]: B0 B1 C0 C1 A 0 1 2 1 2 1 1 3 4 3 4 2 

Update 2021-02-17 with original explode function

def unnesting(df, explode, axis): if axis==1: df1 = pd.concat([df[x].explode() for x in explode], axis=1) return df1.join(df.drop(explode, 1), how='left') else : df1 = pd.concat([ pd.DataFrame(df[x].tolist(), index=df.index).add_prefix(x) for x in explode], axis=1) return df1.join(df.drop(explode, 1), how='left')