Bubble Chart

University Rankings Bubble

Top universities compared by research, teaching scores, and student enrollment.

Output
University Rankings Bubble
Python
import matplotlib.pyplot as plt
import numpy as np

np.random.seed(42)

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

unis = ['MIT', 'Oxford', 'Stanford', 'Cambridge', 'Harvard', 'Caltech', 'Princeton', 'Yale']
research = np.array([99.8, 99.1, 98.7, 98.5, 98.9, 97.8, 95.2, 94.8])
teaching = np.array([97.5, 99.5, 98.2, 99.1, 98.8, 96.5, 97.8, 96.2])
students = np.array([11.5, 24.5, 17.5, 24, 31, 2.4, 8.5, 14])

colors = ['#F54927', '#276CF5', '#6CF527', '#27D3F5', '#C82909', '#F5B027', '#4927F5', '#F5276C']
sizes = students * 50

for glow_mult, glow_alpha in [(2.0, 0.03), (1.6, 0.05), (1.3, 0.08)]:
    ax.scatter(research, teaching, s=sizes*glow_mult, c='#000000', alpha=glow_alpha, edgecolors='none')

ax.scatter(research, teaching, s=sizes, c=colors, alpha=0.85, edgecolors='white', linewidth=2)
ax.scatter(research - np.sqrt(sizes)*0.015, teaching + np.sqrt(sizes)*0.008, s=sizes*0.2, c='white', alpha=0.6, edgecolors='none')

for i, uni in enumerate(unis):
    offset_y = np.sqrt(sizes[i])/2 + 10
    ax.annotate(uni, (research[i], teaching[i]), fontsize=11, color='#1f2937',
                ha='center', va='bottom', xytext=(0, offset_y), textcoords='offset points', fontweight='bold')

ax.text(0.0, 1.08, 'University Rankings', transform=ax.transAxes, fontsize=24, color='#1f2937', fontweight='bold')
ax.text(0.0, 1.02, 'Research vs Teaching Score · Bubble size = Students', transform=ax.transAxes, fontsize=11, color='#6b7280')

ax.set_xlabel('Research Score', fontsize=14, color='#4b5563', fontweight='500', labelpad=15)
ax.set_ylabel('Teaching Score', fontsize=14, color='#4b5563', fontweight='500', labelpad=15)
ax.tick_params(colors='#6b7280', labelsize=11, length=0)
ax.set_xlim(93, 101)
ax.set_ylim(95, 100.5)

for y in [96, 97, 98, 99, 100]:
    ax.axhline(y=y, color='#f3f4f6', linewidth=1, 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