Skip to main content

Python Pandas: How to Fix TypeError: no numeric data to plot

When attempting to generate plots directly from a Pandas DataFrame using its .plot() method (which often relies on Matplotlib), you might encounter the TypeError: no numeric data to plot. This error indicates that the DataFrame or the specific subset of columns you're trying to plot either contains no data or does not have any columns with numeric data types (like integers or floats) that can be meaningfully plotted.

This guide explains the common causes of this error and provides solutions, primarily focusing on data type conversion and ensuring your DataFrame has plottable numeric data.

Understanding the Error: Plotting Numeric Data

Most standard plotting functions (like line plots, bar plots, scatter plots) require numerical data for their axes and values. When you call DataFrame.plot(), Pandas attempts to find numeric columns to use for the plot. If it cannot find any, or if the DataFrame subset being plotted is empty, it raises the TypeError: no numeric data to plot.

Example Setup:

import pandas as pd
import matplotlib.pyplot as plt # For plt.show()

# Sample data where numeric values are stored as strings
data = {
'Year': [2020, 2021, 2022, 2023],
'Revenue': ['100.5M', '120.2M', '150.7M', '180.0M'], # Strings
'Expenses': ['70M', '80M', '95M', '110M'], # Strings
'Region': ['North', 'South', 'North', 'West']
}
df_original = pd.DataFrame(data)
print("Original DataFrame:")
print(df_original)
print("Original dtypes:")
print(df_original.dtypes)

Output:

Original DataFrame:
Year Revenue Expenses Region
0 2020 100.5M 70M North
1 2021 120.2M 80M South
2 2022 150.7M 95M North
3 2023 180.0M 110M West
Original dtypes:
Year int64
Revenue object
Expenses object
Region object
dtype: object
note

If we try to plot 'Revenue' and 'Expenses' directly, we'll get the error.

Cause 1: Columns Have Non-Numeric Data Types (e.g., 'object'/string)

This is the most common cause. Columns that appear numeric might actually be stored as strings (Pandas dtype object) due to how the data was loaded or created.

The Problem

Attempting to plot columns that Pandas sees as non-numeric.

import pandas as pd
import matplotlib.pyplot as plt # For plt.show()

# Sample data where numeric values are stored as strings
data = {
'Year': [2020, 2021, 2022, 2023],
'Revenue': ['100.5M', '120.2M', '150.7M', '180.0M'], # Strings
'Expenses': ['70M', '80M', '95M', '110M'], # Strings
'Region': ['North', 'South', 'North', 'West']
}
df_original = pd.DataFrame(data)
df_plot_attempt = df_original.copy()
try:
# ⛔️ TypeError: no numeric data to plot
df_plot_attempt[['Revenue', 'Expenses']].plot(kind='line')
plt.title("Financials Over Time (Attempt)")
plt.show()
except TypeError as e:
print(f"Caught TypeError: {e}")

Output:

Caught TypeError: no numeric data to plot

The DataFrame.astype() method is used to cast Pandas objects to a specified dtype. You'll need to clean the string data first (e.g., remove 'M') before converting.

import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({
'Year': [2020, 2021, 2022, 2023],
'Revenue': ['100.5M', '120.2M', '150.7M', '180.0M'],
'Expenses': ['70M', '80M', '95M', '110M'],
'Region': ['North', 'South', 'North', 'West']
})
df = df.set_index('Year') # Setting 'Year' as index for a meaningful x-axis

# Clean and convert 'Revenue' and 'Expenses'
# Remove 'M' and convert to float
df['Revenue'] = df['Revenue'].str.replace('M', '').astype(float)
df['Expenses'] = df['Expenses'].str.replace('M', '').astype(float)

print("DataFrame after type conversion:")
print(df)
print()

print("Dtypes after conversion:")
print(df.dtypes)
print()

# ✅ Now plotting should work
df[['Revenue', 'Expenses']].plot(kind='line', title="Financials (Millions)")
plt.ylabel("Amount (Millions)")
plt.show()

Output:

DataFrame after type conversion:
Revenue Expenses Region
Year
2020 100.5 70.0 North
2021 120.2 80.0 South
2022 150.7 95.0 North
2023 180.0 110.0 West

Dtypes after conversion:
Revenue float64
Expenses float64
Region object
dtype: object
note
  • df['Column'].str.replace('M', ''): Removes the 'M' character.
  • .astype(float): Converts the cleaned string column to a floating-point numeric type. You could use int if your data is whole numbers.

Solution 2: Convert Columns to Numeric using pd.to_numeric()

pd.to_numeric() is another robust way to convert. It can also handle errors (e.g., by converting non-numeric values to NaN).

import pandas as pd
import matplotlib.pyplot as plt

df_tonumeric = pd.DataFrame({
'Year': [2020, 2021, 2022, 2023],
'Revenue': ['100.5M', '120.2M', 'Not Available', '180.0M'], # Added a non-numeric string
'Expenses': ['70M', '80M', '95M', '110M'],
'Region': ['North', 'South', 'North', 'West']
})
df_tonumeric = df_tonumeric.set_index('Year')

# Clean and convert using pd.to_numeric
# Forcing errors to NaN allows plotting of valid numbers
df_tonumeric['Revenue'] = pd.to_numeric(df_tonumeric['Revenue'].str.replace('M', ''), errors='coerce')
df_tonumeric['Expenses'] = pd.to_numeric(df_tonumeric['Expenses'].str.replace('M', ''), errors='coerce')

print("DataFrame after pd.to_numeric conversion:")
print(df_tonumeric)
print()

print("Dtypes after pd.to_numeric:")
print(df_tonumeric.dtypes)
print()

df_tonumeric[['Revenue', 'Expenses']].plot(kind='bar', title="Financials (Millions) - with to_numeric")
plt.ylabel("Amount (Millions)")
plt.show()

Output:

DataFrame after pd.to_numeric conversion:
Revenue Expenses Region
Year
2020 100.5 70 North
2021 120.2 80 South
2022 NaN 95 North
2023 180.0 110 West

Dtypes after pd.to_numeric:
Revenue float64
Expenses int64
Region object
dtype: object
note
  • errors='coerce': If pd.to_numeric encounters a value it cannot convert, it replaces it with NaN. This allows the rest of the numeric data to be plotted.

Verifying Data Types with DataFrame.dtypes

Always check the dtypes of your columns before plotting if you suspect this error.

# ... (on your DataFrame 'df') ...
print(df.dtypes)
# Look for 'object' type on columns you expect to be numeric.
# After conversion, they should be 'int64', 'float64', or similar.

Cause 2: DataFrame or Selected Subset is Empty

If the DataFrame you're trying to plot, or the subset of columns selected for plotting, is empty, there's no data to visualize.

The Problem

import pandas as pd
import matplotlib.pyplot as plt

df_empty = pd.DataFrame() # An empty DataFrame

try:
# ⛔️ TypeError: no numeric data to plot
df_empty.plot()
plt.show()
except TypeError as e:
print(f"Error plotting empty DataFrame: {e}")

df_non_numeric_cols_only = pd.DataFrame({'Category': ['A', 'B'], 'Region': ['X', 'Y']})
try:
# ⛔️ TypeError: no numeric data to plot (if only these columns are selected)
df_non_numeric_cols_only.plot()
plt.show()
except TypeError as e:
print(f"Error plotting DataFrame with only non-numeric columns: {e}")

Output:

Error plotting empty DataFrame: no numeric data to plot
Error plotting DataFrame with only non-numeric columns: no numeric data to plot

Solution: Ensure Data is Present

Before plotting, verify that your DataFrame (or the slice you're plotting) is not empty and contains at least one numeric column.

import pandas as pd
import matplotlib.pyplot as plt

df_with_data = pd.DataFrame({'Values': [10, 20, 15, 25]})
df_empty_check = pd.DataFrame()

if not df_with_data.empty and any(dtype.kind in 'ifc' for dtype in df_with_data.dtypes):
print("Plotting DataFrame with data:")
df_with_data.plot(title="Data Plot")
plt.show()
else:
print("DataFrame with data is empty or has no numeric columns to plot.")

if not df_empty_check.empty and any(dtype.kind in 'ifc' for dtype in df_empty_check.dtypes):
print("Plotting empty DataFrame (check):") # This won't run
df_empty_check.plot()
plt.show()
else:
print("Empty DataFrame check: DataFrame is empty or has no numeric columns.")

Output:

Plotting DataFrame with data:
Empty DataFrame check: DataFrame is empty or has no numeric columns.
  • df.empty: Checks if the DataFrame has any data.
  • any(dtype.kind in 'ifc' for dtype in df.dtypes): Checks if any column has an integer (i), float (f), or complex (c) data type.

Choosing Columns for Plotting

When you call df.plot(), Pandas tries to plot all numeric columns. If you only want to plot specific numeric columns, select them first:

import pandas as pd
import matplotlib.pyplot as plt

df_converted = pd.DataFrame({
'Year': [2020, 2021, 2022, 2023],
'Revenue': [100.5, 120.2, 150.7, 180.0],
'Expenses': [70.0, 80.0, 95.0, 110.0],
'Region': ['North', 'South', 'North', 'West']
}).set_index('Year')


# ✅ Plot only the 'Revenue' column
df_converted['Revenue'].plot(kind='line', title="Revenue Over Time", legend=True)
plt.ylabel("Amount (Millions)")
plt.show()

# ✅ Plot 'Revenue' and 'Expenses'
df_converted[['Revenue', 'Expenses']].plot(kind='area', title="Financials (Area Plot)", stacked=False)
plt.ylabel("Amount (Millions)")
plt.show()

Conclusion

The Pandas TypeError: no numeric data to plot arises primarily from two issues:

  1. Non-Numeric Columns: The columns you intend to plot are stored as strings (object dtype) or other non-numeric types. Solution: Clean the data if necessary (e.g., remove currency symbols, units like 'M') and then convert the columns to a numeric type using df['col'].astype(float) or pd.to_numeric(df['col'], errors='coerce').
  2. Empty DataFrame/Selection: The DataFrame or the subset of columns you're trying to plot contains no data. Solution: Ensure your DataFrame is populated and your selection results in at least one numeric column with data.

Always check df.dtypes to confirm your data types before plotting, and verify that your DataFrame is not empty. By ensuring your data is in the correct numeric format, you can leverage Pandas' powerful plotting capabilities.