Bubble Chart

Cyber Threats Analysis Bubble

Security threats visualized by severity, frequency, and financial impact.

Output
Cyber Threats Analysis Bubble
Python
import matplotlib.pyplot as plt
import numpy as np

np.random.seed(42)

fig, ax = plt.subplots(figsize=(14, 9), facecolor='#0a0a0f')
ax.set_facecolor('#0a0a0f')

threats = ['Ransomware', 'Phishing', 'DDoS', 'Data Breach', 'Supply Chain', 'Zero-Day', 'Insider', 'APT']
severity = np.array([9.5, 6, 7, 9, 8.5, 9.8, 7.5, 9.2])
frequency = np.array([620, 3400, 850, 290, 45, 15, 180, 25])
avg_cost = np.array([4.5, 0.5, 0.8, 4.2, 8.5, 12, 2.5, 15])

colors = ['#C82909', '#F5B027', '#27D3F5', '#F5276C', '#4927F5', '#9C2007', '#6CF527', '#F54927']
sizes = avg_cost * 100

for glow_mult, glow_alpha in [(3.5, 0.02), (2.8, 0.04), (2.2, 0.06), (1.7, 0.10), (1.3, 0.15)]:
    ax.scatter(severity, frequency, s=sizes*glow_mult, c=colors, alpha=glow_alpha, edgecolors='none')

ax.scatter(severity, frequency, s=sizes, c=colors, alpha=0.9, edgecolors='none')
ax.scatter(severity, frequency, s=sizes*0.4, c=colors, alpha=0.4, edgecolors='none')
ax.scatter(severity - np.sqrt(sizes)*0.008, frequency + np.sqrt(sizes)*2, s=sizes*0.15, c='white', alpha=0.5, edgecolors='none')

for i, threat in enumerate(threats):
    offset_y = np.sqrt(sizes[i])/2 + 10
    ax.annotate(threat, (severity[i], frequency[i]), fontsize=10, color='white',
                ha='center', va='bottom', xytext=(0, offset_y), textcoords='offset points', fontweight='bold')

ax.text(0.0, 1.08, 'Cyber Threats Analysis', transform=ax.transAxes, fontsize=24, color='white', fontweight='bold')
ax.text(0.0, 1.02, 'Severity vs Frequency · Bubble size = Avg Cost', transform=ax.transAxes, fontsize=11, color='#555555')

ax.set_xlabel('Severity Score (1-10)', fontsize=14, color='#888888', fontweight='500', labelpad=15)
ax.set_ylabel('Annual Incidents (Thousands)', fontsize=14, color='#888888', fontweight='500', labelpad=15)
ax.tick_params(colors='#555555', labelsize=11, length=0)
ax.set_xlim(5, 10.5)

for y in [0, 1000, 2000, 3000, 4000]:
    ax.axhline(y=y, color='#1a1a2e', linewidth=0.8, zorder=0)
for spine in ax.spines.values():
    spine.set_visible(False)

plt.tight_layout()
plt.show()
Library

Matplotlib

Category

Pairwise Data

Did this help you?

Support PyLucid to keep it free & growing

Support