How to Create Radar Charts in Python: Plotly vs Matplotlib Comparison

Create Radar Charts Python Plotly vs Matplotlib Comparison Image by Author
 

Radar charts, also called spider or web charts, display multiple variables on axes that radiate from a central point. Each entity forms a polygon connecting its values across all variables, making it easy to compare patterns and identify strengths or weaknesses at a glance.

These charts are useful for performance evaluations, skill assessments, and multi-criteria comparisons. For example, you might compare programming languages across different attributes, evaluate business performance metrics, or analyze survey responses with multiple dimensions.

In this tutorial, we’ll build radar charts using two popular Python libraries: Plotly and Matplotlib. You’ll learn when to use each approach, how to handle data with different scales, and get hands-on experience with working code examples.

Prerequisites and Setup

We’ll use several Python libraries for this tutorial. Install them using pip:

 
pip install numpy pandas matplotlib plotly scikit-learn

Now let’s import the required packages:

 
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import plotly.graph_objects as go
from sklearn.preprocessing import MinMaxScaler
from math import pi

This imports the core libraries we need for data manipulation, visualization, and scaling.

Sample Dataset Preparation

We’ll compare four programming languages across six categories. Each language receives a score from 1-10 for different attributes:

 
categories = ['Learning Curve', 'Performance', 'Community Support', 
              'Job Market', 'Versatility', 'Documentation']

languages = {
    'Python': [9, 7, 9, 9, 8, 9],
    'JavaScript': [8, 6, 8, 10, 9, 7],
    'Java': [6, 8, 8, 8, 7, 8],
    'C++': [4, 10, 6, 7, 8, 7]
}

df = pd.DataFrame(languages, index=categories)

This creates our comparison dataset with consistent scoring across all categories.

Method 1: Creating Interactive Radar Charts with Plotly

Plotly excels at creating interactive visualizations with minimal code. Each programming language becomes a separate trace on the radar chart:

 
fig = go.Figure()

for language in languages.keys():
    fig.add_trace(go.Scatterpolar(
        r=languages[language],
        theta=categories,
        fill='toself',
        name=language,
        opacity=0.7
    ))

The fill=’toself’ parameter creates the filled polygon shape, while opacity=0.7 makes overlapping areas visible.

Now we customize the chart layout and display settings:

 
fig.update_layout(
    polar=dict(
        radialaxis=dict(
            visible=True,
            range=[0, 10]
        )),
    showlegend=True,
    title={
        'text': "Programming Languages Skill Comparison",
        'x': 0.5,
        'xanchor': 'center'
    },
    width=600,
    height=600
)

fig.show()

This produces an interactive chart where users can hover over data points, toggle languages on and off, and zoom in on specific areas.

radar charts python
 

Plotly Advantages

Plotly offers several benefits for radar charts. The interactive features let users explore data dynamically, making it ideal for dashboards and presentations. The default styling looks professional with minimal customization, and the charts work well in web applications and Jupyter notebooks.

Plotly Limitations

Interactive features require JavaScript rendering, which may not work in all environments. The library adds dependencies to your project, and the charts aren’t suitable for static publications that need precise formatting control.

Method 2: Creating Static Radar Charts with Matplotlib

Matplotlib requires more setup but provides complete control over every visual element. We start by calculating the angles for each category:

 
fig, ax = plt.subplots(figsize=(8, 8), subplot_kw=dict(projection='polar'))

angles = [n / float(len(categories)) * 2 * pi for n in range(len(categories))]
angles += angles[:1]

The angles list contains the radial positions for each category. We add the first angle to the end to close the polygon.

Next, we plot each programming language as a separate line and filled area:

 
colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4']

for i, (language, values) in enumerate(languages.items()):
    values_closed = values + values[:1]
    ax.plot(angles, values_closed, 'o-', linewidth=2, 
            label=language, color=colors[i])
    ax.fill(angles, values_closed, alpha=0.25, color=colors[i])

Each language gets its own color and styling. The values + values[:1] closes the polygon by duplicating the first value.

Finally, we customize the chart appearance:

 
ax.set_xticks(angles[:-1])
ax.set_xticklabels(categories)
ax.set_ylim(0, 10)
ax.set_yticks(range(0, 11, 2))
ax.set_title('Programming Languages Comparison', size=16, pad=20)
ax.legend(loc='upper right', bbox_to_anchor=(1.3, 1.0))

plt.tight_layout()
plt.show()

This creates a publication-ready static chart with full control over fonts, colors, and positioning.

radar charts python

 

Matplotlib Advantages

Matplotlib works everywhere Python runs and creates high-quality static images perfect for reports and publications. You control every aspect of the visualization, from line thickness to label positioning. The library is lightweight compared to Plotly.

Matplotlib Limitations

Creating radar charts requires more code and manual calculations. There’s no built-in interactivity, and achieving professional styling often needs additional customization work.

Handling Mixed-Scale Data

Oftentimes you will deal with data that comes in different units and scales. Revenue figures in millions will dominate satisfaction scores on a 1-5 scale, distorting the radar chart. Here’s how to solve this problem:

 
business_metrics = {
    'Revenue': [2500000, 1800000, 3200000],
    'Employee Count': [45, 55, 78],
    'Customer Satisfaction': [4.2, 4.7, 4.5],
    'Market Share': [0.14, 0.15, 0.10],
    'Years in Business': [12, 8, 20]
}

companies = ['Company A', 'Company B', 'Company C']
raw_df = pd.DataFrame(business_metrics, index=companies)

The original data shows the scale problem clearly, with revenue values in millions while satisfaction scores range from 4-5. We’ll use MinMaxScaler to transform all variables to a 0-10 scale:

 
scaler = MinMaxScaler(feature_range=(0, 10))
scaled_data = scaler.fit_transform(raw_df)

scaled_df = pd.DataFrame(scaled_data, 
                        index=companies, 
                        columns=business_metrics.keys())

Now all metrics use the same scale, making fair comparisons possible. Let’s create a radar chart with the scaled data:

 
fig = go.Figure()

metrics = list(business_metrics.keys())
colors_scaled = ['#FF6B6B', '#4ECDC4', '#45B7D1']

for i, company in enumerate(companies):
    fig.add_trace(go.Scatterpolar(
        r=scaled_df.loc[company].values,
        theta=metrics,
        fill='toself',
        name=company,
        line=dict(color=colors_scaled[i])
    ))

fig.update_layout(
    polar=dict(radialaxis=dict(visible=True, range=[0, 10])),
    title={
        'text': "Business Performance Comparison (Scaled Data)",
        'x': 0.5,
        'xanchor': 'center'
    },
    showlegend=True,
    legend=dict(
        x=0.8,  
        y=0.5,   
        xanchor='left',
        yanchor='middle'
    )
)

fig.show()

radar charts python

 
The scaled chart reveals meaningful patterns that were hidden when revenue dominated the visualization. We can create a similar scaled version using Matplotlib: 

 
fig, ax = plt.subplots(figsize=(7, 7), subplot_kw=dict(projection='polar'))

# Categories (metrics) and angles
metrics = list(business_metrics.keys())
angles = [n / float(len(metrics)) * 2 * pi for n in range(len(metrics))]
angles += angles[:1]  # Complete the circle

# Plot each company
colors = ['#FF6B6B', '#4ECDC4', '#45B7D1']
for i, company in enumerate(companies):
    values = scaled_df.loc[company].values.tolist()
    values_closed = values + values[:1]
    ax.plot(angles, values_closed, 'o-', linewidth=2, label=company, color=colors[i])
    ax.fill(angles, values_closed, alpha=0.25, color=colors[i])

# Customize the chart
ax.set_xticks(angles[:-1])
ax.set_xticklabels(metrics)
ax.set_ylim(0, 10)
ax.set_yticks(range(0, 11, 2))
ax.set_title('Business Performance Comparison (Scaled)', size=16, y=1.1, x=0.5)
ax.legend(loc='upper right', bbox_to_anchor=(1.3, 1.0))
ax.grid(True)

plt.tight_layout()
plt.show()

 

radar charts python

 

Scaling Considerations

Scaling changes interpretation. A company dominating in raw revenue might show modest advantages on the radar chart, while another company might appear to perform better overall due to more balanced scores across all scaled dimensions. The choice of scaling method impacts your radar chart’s appearance and interpretation.

MinMaxScaler transforms data to a fixed range, commonly (0-1) for simplicity or (0-10) for intuitive scoring. However, it’s sensitive to outliers, which can compress most values into a narrow range.

For better outlier handling, QuantileTransformer offers an alternative that scales data based on percentile ranks, providing more balanced visual distribution when your data contains extreme values.

Choosing the Right Approach

Select Plotly when building interactive dashboards, teaching materials, or web applications where users benefit from exploring the data. The hover tooltips and toggle features enhance understanding.

Choose Matplotlib for academic papers, printed reports, or any context requiring static images with precise formatting. You’ll have complete control over the final appearance.

Apply scaling whenever your variables use different units or ranges. This is especially important for business metrics, survey data, or any analysis combining measurements from different domains.

Conclusion

Radar charts provide a useful way to visualize multi-dimensional comparisons in Python. Plotly offers interactive features perfect for exploration and presentation, while Matplotlib delivers precise control for publication-quality static charts. When working with mixed-scale data, choosing an appropriate scaling method ensures fair comparisons across all dimensions while preserving the analytical insights most relevant to your specific use case.

Both approaches have their place in data visualization. By understanding their strengths and limitations, you can choose the right tool for your specific needs and audience.

Leave a Reply

Your email address will not be published. Required fields are marked *