Skip to content

Python Pandas: How to Multiply DataFrame Columns (Element-wise)

Learn how to perform element-wise multiplication between DataFrame columns in Pandas using the * operator, Series.mul(), and conditional logic for calculations like revenue or weighted scores.

Performing element-wise multiplication between two or more columns in a Pandas DataFrame is a common operation in data analysis, often used for calculating totals, weighted scores, or new features. Pandas provides several straightforward ways to achieve this, including using the standard multiplication operator (*) and the DataFrame.mul() method.

This guide explains how to multiply DataFrame columns, handle potential non-numeric data, and perform conditional multiplication.

The Goal: Element-wise Column Multiplication

Given a Pandas DataFrame, we want to create a new column (or update an existing one) where each value is the product of the corresponding values from two or more specified columns in the same row. For example, multiplying a 'Price' column by a 'Quantity' column to get a 'Total_Sale' column.

Example DataFrame

import pandas as pd

data = {
    'ProductName': ['Apple', 'Banana', 'Orange', 'Grape'],
    'Price_Per_Unit': [0.5, 0.25, 0.4, 1.5],
    'Quantity_Sold': [100, 150, 200, 50],
    'Discount_Factor': [1.0, 0.9, 1.0, 0.8], # 1.0 means no discount
    'Category': ['Fruit', 'Fruit', 'Fruit', 'Fruit']
}

df_original = pd.DataFrame(data)
print("Original DataFrame:")
print(df_original)

Output:

Original DataFrame:
  ProductName  Price_Per_Unit  Quantity_Sold  Discount_Factor Category
0       Apple            0.50            100              1.0    Fruit
1      Banana            0.25            150              0.9    Fruit
2      Orange            0.40            200              1.0    Fruit
3       Grape            1.50             50              0.8    Fruit

This is the most direct and Pythonic way to perform element-wise multiplication between Series (DataFrame columns).

Multiplying Two Columns

Select the columns and use the * operator. Assign the result to a new column.

import pandas as pd

df = pd.DataFrame({
    'ProductName': ['Apple', 'Banana'],
    'Price_Per_Unit': [0.5, 0.25],
    'Quantity_Sold': [100, 150]
})

df['Total_Revenue'] = df['Price_Per_Unit'] * df['Quantity_Sold']

print("DataFrame with 'Total_Revenue' column:")
print(df)

Output:

DataFrame with 'Total_Revenue' column:
  ProductName  Price_Per_Unit  Quantity_Sold  Total_Revenue
0       Apple            0.50            100           50.0
1      Banana            0.25            150           37.5

Multiplying More Than Two Columns

You can chain multiplications.

import pandas as pd

df = pd.DataFrame({
    'ProductName': ['Apple', 'Banana'],
    'Price_Per_Unit': [0.5, 0.25],
    'Quantity_Sold': [100, 150],
    'Discount_Factor': [1.0, 0.9]
})

df['Net_Revenue'] = df['Price_Per_Unit'] * df['Quantity_Sold'] * df['Discount_Factor']

print("DataFrame with 'Net_Revenue' column:")
print(df)

Output:

DataFrame with 'Net_Revenue' column:
  ProductName  Price_Per_Unit  Quantity_Sold  Discount_Factor  Net_Revenue
0       Apple            0.50            100              1.0        50.00
1      Banana            0.25            150              0.9        33.75

Ensuring Numeric Data Types (astype())

Multiplication requires numeric data types (e.g., int, float). If your columns are stored as strings (object dtype), you must convert them to a numeric type first using astype().

import pandas as pd

data_str = {
    'Price_Str': ['10.5', '20.0', '5.75'],
    'Quantity_Str': ['5', '3', '10'],
    'Item': ['A', 'B', 'C']
}
df_str = pd.DataFrame(data_str)
print("DataFrame with string numeric values:")
print(df_str.dtypes) # Price_Str and Quantity_Str will be 'object'
print()

price_numeric = df_str['Price_Str'].astype(float)
quantity_numeric = df_str['Quantity_Str'].astype(int) # Or float

df_str['Total_Value'] = price_numeric * quantity_numeric

print("DataFrame after converting to numeric and multiplying:")
print(df_str)

Output:

DataFrame with string numeric values:
Price_Str       object
Quantity_Str    object
Item            object
dtype: object

DataFrame after converting to numeric and multiplying:
  Price_Str Quantity_Str Item  Total_Value
0      10.5            5    A         52.5
1      20.0            3    B         60.0
2      5.75           10    C         57.5

Method 2: Using Series.mul() Method

Each Pandas Series (a DataFrame column) has a .mul() method for element-wise multiplication. This is equivalent to the * operator for basic multiplication but offers a fill_value parameter for handling missing data.

Basic Usage

import pandas as pd

df = pd.DataFrame({
    'ProductName': ['Apple', 'Banana'],
    'Price_Per_Unit': [0.5, 0.25],
    'Quantity_Sold': [100, 150]
})

df['Total_Revenue_mul'] = df['Price_Per_Unit'].mul(df['Quantity_Sold'])

print("DataFrame with 'Total_Revenue_mul' (using .mul()):")
print(df)

Output:

DataFrame with 'Total_Revenue_mul' (using .mul()):
  ProductName  Price_Per_Unit  Quantity_Sold  Total_Revenue_mul
0       Apple            0.50            100               50.0
1      Banana            0.25            150               37.5

Handling Missing Values (fill_value)

If one of the Series has NaN values, the result of multiplication with * or default mul() will also be NaN. The fill_value parameter in mul() allows you to substitute NaNs with a specific value (e.g., 0 or 1) before the multiplication occurs for that specific operation.

import pandas as pd
import numpy as np

data_nan = {
    'Price': [10, 20, np.nan, 40],
    'Quantity': [2, np.nan, 5, 3]
}
df_nan = pd.DataFrame(data_nan)
print("DataFrame with NaNs:")
print(df_nan)
print()

df_nan['Total_default'] = df_nan['Price'] * df_nan['Quantity']
print("Total (default, NaN propagates):\n", df_nan['Total_default'])
print()

df_nan['Total_fill_0'] = df_nan['Price'].mul(df_nan['Quantity'], fill_value=0)

print("Total (using .mul() with fill_value=0):")
print(df_nan)

Output:

DataFrame with NaNs:
   Price  Quantity
0   10.0       2.0
1   20.0       NaN
2    NaN       5.0
3   40.0       3.0

Total (default, NaN propagates):
 0     20.0
1      NaN
2      NaN
3    120.0
Name: Total_default, dtype: float64

Total (using .mul() with fill_value=0):
   Price  Quantity  Total_default  Total_fill_0
0   10.0       2.0           20.0          20.0
1   20.0       NaN            NaN           0.0
2    NaN       5.0            NaN           0.0
3   40.0       3.0          120.0         120.0

Choose fill_value carefully based on how you want missing data to affect the product (e.g., fill_value=1 if missing means "no change to the other factor").

Conditional Multiplication of Columns

Sometimes you only want to multiply columns if a certain condition is met for that row.

Using numpy.where() or Series.where()

np.where(condition, value_if_true, value_if_false) is excellent for this.

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'ProductName': ['Apple', 'Banana', 'Orange'],
    'Price_Per_Unit': [0.5, 0.25, 0.4],
    'Quantity_Sold': [100, 150, 200],
    'On_Sale': [False, True, False]
})

df['Conditional_Total'] = np.where(
    df['On_Sale'] == True,                             # Condition
    df['Price_Per_Unit'] * df['Quantity_Sold'],        # Value if True
    0                                                  # Value if False (e.g., no sale value)
)

print("DataFrame with conditional multiplication using np.where():")
print(df)

Output:

DataFrame with conditional multiplication using np.where():
  ProductName  Price_Per_Unit  Quantity_Sold  On_Sale  Conditional_Total
0       Apple            0.50            100    False                0.0
1      Banana            0.25            150     True               37.5
2      Orange            0.40            200    False                0.0

Series.where(condition, other_value) also works: df['total'] = (df['price'] * df['amount']).where(df['product'] == 'apple', other=0). It keeps values where condition is True and replaces with other_value where False.

Using DataFrame.apply() with a Custom Function

For more complex row-wise conditional logic, apply(axis=1) can be used.

import pandas as pd

df = pd.DataFrame({
    'ProductName': ['Apple', 'Banana', 'Orange'],
    'Price_Per_Unit': [0.5, 0.25, 0.4],
    'Quantity_Sold': [100, 150, 200],
    'On_Sale': [False, True, False]
})

def calculate_total_apply(row):
  if row['On_Sale']:
    return row['Price_Per_Unit'] * row['Quantity_Sold']
  else:
    return 0 # Or some other default for non-sale items

df['Conditional_Total_apply'] = df.apply(calculate_total_apply, axis=1)

print("DataFrame with conditional multiplication using apply():")
print(df)

Output:

DataFrame with conditional multiplication using apply():
  ProductName  Price_Per_Unit  Quantity_Sold  On_Sale  Conditional_Total_apply
0       Apple            0.50            100    False                      0.0
1      Banana            0.25            150     True                     37.5
2      Orange            0.40            200    False                      0.0

apply(axis=1) is generally less performant than vectorized solutions like np.where or direct arithmetic for simple conditions but offers more flexibility for intricate logic.

Conclusion

Multiplying columns in a Pandas DataFrame is a fundamental element-wise operation:

  • The most direct method is using the standard multiplication operator (*) between selected columns: df['NewCol'] = df['ColA'] * df['ColB']. This also extends to more than two columns.
  • The Series.mul(other_series, fill_value=...) method provides an alternative, especially useful for its fill_value parameter to handle NaNs during the operation.
  • Ensure columns are of numeric type (int or float) before multiplication; use astype() if necessary.
  • For conditional multiplication, numpy.where() (or Series.where()) is efficient and recommended for clear conditions. DataFrame.apply(axis=1) offers more flexibility for complex row-wise logic.

These techniques allow for powerful and efficient calculations across your DataFrame columns.

Navigation