Beeswarm Plot

Wine Quality Score by Grape Variety

Expert ratings across different wine types

Output
Wine Quality Score by Grape Variety
Python
import numpy as np
import matplotlib.pyplot as plt

np.random.seed(308)
BG_COLOR = '#0a0a0f'
TEXT_COLOR = 'white'
COLORS = ['#9C2007', '#F5276C', '#F5B027', '#5314E6']

def simple_beeswarm(y, nbins=None, width=1.):
    y = np.asarray(y)
    if nbins is None:
        nbins = np.ceil(len(y) / 6).astype(int)
    nn, ybins = np.histogram(y, bins=nbins)
    nmax = nn.max()
    x = np.zeros(len(y))
    ibs = []
    for ymin, ymax in zip(ybins[:-1], ybins[1:]):
        i = np.nonzero((y > ymin) * (y <= ymax))[0]
        ibs.append(i)
    dx = width / (nmax // 2) if nmax > 1 else width
    for i in ibs:
        yy = y[i]
        if len(i) > 1:
            j = len(i) % 2
            i = i[np.argsort(yy)]
            a = i[j::2]
            b = i[j+1::2]
            x[a] = (0.5 + j / 3 + np.arange(len(b))) * dx
            x[b] = (0.5 + j / 3 + np.arange(len(b))) * -dx
    return x

varieties = ['Cabernet', 'Merlot', 'Chardonnay', 'Pinot Noir']
data = {
    'Cabernet': np.random.beta(8, 2, 50) * 100,
    'Merlot': np.random.beta(7, 2.5, 55) * 100,
    'Chardonnay': np.random.beta(7.5, 2, 48) * 100,
    'Pinot Noir': np.random.beta(8.5, 2, 45) * 100
}

fig, ax = plt.subplots(figsize=(10, 6), facecolor=BG_COLOR)
ax.set_facecolor(BG_COLOR)

boxplot_data = []
for i, (variety, values) in enumerate(data.items()):
    x = simple_beeswarm(values, width=0.3)
    ax.scatter(x + i + 1, values, c=COLORS[i], alpha=0.7, s=45, edgecolors='white', linewidth=0.5)
    boxplot_data.append(values)

bp = ax.boxplot(boxplot_data, positions=range(1, len(varieties)+1), widths=0.5, patch_artist=True)
for patch in bp['boxes']:
    patch.set_facecolor('none')
    patch.set_edgecolor('#666')
for element in ['whiskers', 'caps', 'medians']:
    for item in bp[element]:
        item.set_color('#666')

ax.set_xticks(range(1, len(varieties)+1))
ax.set_xticklabels(varieties, color=TEXT_COLOR)
ax.set_xlabel('Grape Variety', fontsize=12, color=TEXT_COLOR, fontweight='500')
ax.set_ylabel('Quality Score', fontsize=12, color=TEXT_COLOR, fontweight='500')
ax.set_title('Wine Quality by Variety', fontsize=14, color=TEXT_COLOR, fontweight='bold', pad=15)

ax.tick_params(colors='#888', labelsize=10)
for spine in ax.spines.values():
    spine.set_color('#333')

plt.tight_layout()
plt.show()
Library

Matplotlib

Category

Statistical

Did this help you?

Support PyLucid to keep it free & growing

Support