Skip to content

Add diagrams for rand_distr #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
May 24, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,531 changes: 1,531 additions & 0 deletions charts/beta.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,517 changes: 1,517 additions & 0 deletions charts/binomial.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,470 changes: 1,470 additions & 0 deletions charts/cauchy.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,402 changes: 1,402 additions & 0 deletions charts/chi_squared.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added charts/dirichlet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,171 changes: 1,171 additions & 0 deletions charts/exponential.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,056 changes: 1,056 additions & 0 deletions charts/exponential_exp1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,520 changes: 1,520 additions & 0 deletions charts/fisher_f.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,744 changes: 1,744 additions & 0 deletions charts/frechet.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,532 changes: 1,532 additions & 0 deletions charts/gamma.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,571 changes: 1,571 additions & 0 deletions charts/geometric.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,466 changes: 1,466 additions & 0 deletions charts/gumbel.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,581 changes: 1,581 additions & 0 deletions charts/hypergeometric.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,436 changes: 1,436 additions & 0 deletions charts/inverse_gaussian.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,575 changes: 1,575 additions & 0 deletions charts/log_normal.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,516 changes: 1,516 additions & 0 deletions charts/normal.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,740 changes: 1,740 additions & 0 deletions charts/normal_inverse_gaussian.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,228 changes: 1,228 additions & 0 deletions charts/pareto.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,744 changes: 1,744 additions & 0 deletions charts/pert.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,583 changes: 1,583 additions & 0 deletions charts/poisson.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,586 changes: 1,586 additions & 0 deletions charts/skew_normal.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,351 changes: 1,351 additions & 0 deletions charts/standard_geometric.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,159 changes: 1,159 additions & 0 deletions charts/standard_normal.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,615 changes: 1,615 additions & 0 deletions charts/student_t.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,237 changes: 1,237 additions & 0 deletions charts/triangular.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15,516 changes: 15,516 additions & 0 deletions charts/unit_ball.svg

Large diffs are not rendered by default.

907 changes: 907 additions & 0 deletions charts/unit_circle.svg

Large diffs are not rendered by default.

886 changes: 886 additions & 0 deletions charts/unit_disc.svg

Large diffs are not rendered by default.

6,218 changes: 6,218 additions & 0 deletions charts/unit_sphere.svg

Large diffs are not rendered by default.

1,500 changes: 1,500 additions & 0 deletions charts/weibull.svg

Large diffs are not rendered by default.

1,575 changes: 1,575 additions & 0 deletions charts/zeta.svg

Large diffs are not rendered by default.

1,556 changes: 1,556 additions & 0 deletions charts/zipf.svg

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
numpy==1.26.4
matplotlib==3.8.4
scipy==1.13.0
python-ternary==1.0.8
35 changes: 35 additions & 0 deletions src/distributions/beta.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import beta


def save_to(directory: str, extension: str):
# Defining the Beta distribution PDF
def y(a, b, x):
y = beta.pdf(x, a, b)
y[y > 4] = np.nan
return y

inputs = [(0.5, 0.5), (5, 1), (1, 3), (2, 2), (2, 5)]
# Possible values for the distribution
x = np.linspace(0, 1, 1000)

# Creating the figure and the axis
fig, ax = plt.subplots()

# Plotting the PDF for each value of alpha and beta
for a, b in inputs:
ax.plot(x, y(a, b, x), label=f'α = {a}, β = {b}')

# Adding title and labels
ax.set_title('Beta distribution')
ax.set_xlabel('x')
ax.set_ylabel('Probability density')

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)

plt.savefig(f"{directory}/beta.{extension}")
plt.close()
33 changes: 33 additions & 0 deletions src/distributions/binomial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import binom


def save_to(directory: str, extension: str):
inputs = [(10, 0.2), (10, 0.6)]
# Possible outcomes for a Binomial distributed variable
outcomes = np.arange(0, 11)
width = 0.5

# Creating the figure and the axis
fig, ax = plt.subplots()

# Plotting the PMF for each value of n and p
for i, (n, p) in enumerate(inputs):
ax.bar(outcomes + i * width - width / 2, binom.pmf(outcomes, n, p), width=width, label=f'n = {n}, p = {p}')

# Adding title and labels
ax.set_title('Binomial distribution')
ax.set_xlabel('k (number of successes)')
ax.set_ylabel('Probability')
ax.set_xticks(outcomes) # set the ticks to be the outcome values

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.savefig(f"{directory}/binomial.{extension}")
plt.close()
31 changes: 31 additions & 0 deletions src/distributions/cauchy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import numpy as np
import matplotlib.pyplot as plt


def save_to(directory: str, extension: str):
# Possible values for the distribution
x = np.linspace(-7, 7, 1000)

# Creating the figure and the axis
fig, ax = plt.subplots()

inputs = [(0, 1), (0, 0.5), (0, 2), (-2, 1)]

# Plotting the PDF for the Cauchy distribution
for x0, gamma in inputs:
ax.plot(x, 1 / (np.pi * gamma * (1 + ((x - x0) / gamma)**2)), label=f'x₀ = {x0}, γ = {gamma}')

# Adding title and labels
ax.set_title('Cauchy distribution')
ax.set_xlabel('x')
ax.set_ylabel('Probability density')

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.savefig(f"{directory}/cauchy.{extension}")
plt.close()
34 changes: 34 additions & 0 deletions src/distributions/chi_squared.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import chi2


def save_to(directory: str, extension: str):
def y(x, df):
y = chi2.pdf(x, df)
y[y > 1.05] = np.nan
return y
# Degrees of freedom for the distribution
df_values = [1, 2, 3, 5, 9]
# Possible values for the distribution
x = np.linspace(0, 10, 1000)

# Creating the figure and the axis
fig, ax = plt.subplots()

# Plotting the PDF for each value of the degrees of freedom
for df in df_values:
ax.plot(x, y(x, df), label=f'k = {df}')

# Adding title and labels
ax.set_title('Chi-squared distribution')
ax.set_xlabel('Chi-squared statistic')
ax.set_ylabel('Probability density')

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)

plt.savefig(f"{directory}/chi_squared.{extension}")
plt.close()
76 changes: 76 additions & 0 deletions src/distributions/dirichlet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.tri as tri
from math import gamma
import ternary


# Code source: https://blog.bogatron.net/blog/2014/02/02/visualizing-dirichlet-distributions/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice little article.

class Dirichlet(object):
def __init__(self, alpha):
self._alpha = np.array(alpha)
self._coef = gamma(np.sum(self._alpha)) / np.multiply.reduce([gamma(a) for a in self._alpha])

def pdf(self, x):
"""Returns pdf value for `x`."""
return self._coef * np.multiply.reduce([xx ** (aa - 1) for (xx, aa) in zip(x, self._alpha)])


def save_to(directory: str, _: str):
extension = "png" # Hardcode png output format. SVG file size for this distribution is ~100x larger.
corners = np.array([[0, 0], [1, 0], [0.5, np.sqrt(0.75)]])
AREA = 0.5 * 1 * np.sqrt(0.75)
triangle = tri.Triangulation(corners[:, 0], corners[:, 1])

pairs = [corners[np.roll(range(3), -i)[1:]] for i in range(3)]
tri_area = lambda xy, pair: 0.5 * np.linalg.norm(np.cross(*(pair - xy)))

def xy2bc(xy, tol=1.e-4):
coords = np.array([tri_area(xy, p) for p in pairs]) / AREA
return np.clip(coords, tol, 1.0 - tol)

def draw_pdf_contours(ax, alphas, nlevels=200, subdiv=8):
refiner = tri.UniformTriRefiner(triangle)
trimesh = refiner.refine_triangulation(subdiv=subdiv)
pvals = [Dirichlet(alphas).pdf(xy2bc(xy)) for xy in zip(trimesh.x, trimesh.y)]

contour = ax.tricontourf(trimesh, pvals, nlevels, cmap='plasma')
ternary.plt.colorbar(contour, ax=ax, orientation='vertical', fraction=0.05, pad=0.05)

ax.axis('equal')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)

tax = ternary.TernaryAxesSubplot(ax=ax, scale=1.0)

tax.boundary(linewidth=1.0)

tax.ticks(axis='lbr', linewidth=1, multiple=0.2, tick_formats="%.1f", offset=0.02)

fontsize = 13
tax.set_title(f"α = {alphas}", fontsize=fontsize, pad=20)
tax.right_axis_label("$x_3$", fontsize=fontsize, offset=0.15)
tax.left_axis_label("$x_1$", fontsize=fontsize, offset=0.15)
tax.bottom_axis_label("$x_2$", fontsize=fontsize)
tax._redraw_labels() # Won't do this automatically because of the way we are saving the plot

tax.clear_matplotlib_ticks()

inputs = [
[1.5, 1.5, 1.5],
[5.0, 5.0, 5.0],
[1.0, 2.0, 2.0],
[2.0, 4.0, 8.0]
]

fig, axes = plt.subplots(2, 2, figsize=(12, 10))
for ax, alphas in zip(axes.flatten(), inputs):
draw_pdf_contours(ax, alphas)

# Adding the main title and colorbar
ternary.plt.suptitle('Dirichlet Distribution', fontsize=16)

ternary.plt.savefig(f"{directory}/dirichlet.{extension}", bbox_inches='tight', pad_inches=0.5)
plt.close()
30 changes: 30 additions & 0 deletions src/distributions/exponential.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import expon


def save_to(directory: str, extension: str):
# Possible values of lambda for the distribution
lambda_values = [1, 0.5, 2]
# Possible values for the distribution
x = np.linspace(0, 5, 1000)

# Creating the figure and the axis
fig, ax = plt.subplots()

# Plotting the PDF for each value of lambda
for lmbda in lambda_values:
ax.plot(x, expon.pdf(x, scale=1 / lmbda), label=f'λ = {lmbda}')

# Adding title and labels
ax.set_title('Exponential distribution')
ax.set_xlabel('x')
ax.set_ylabel('Probability density')

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)

plt.savefig(f"{directory}/exponential.{extension}")
plt.close()
29 changes: 29 additions & 0 deletions src/distributions/exponential_exp1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import expon


def save_to(directory: str, extension: str):
# Fixed value for lambda
lmbda = 1
# Possible values for the distribution
x = np.linspace(0, 5, 1000)

# Creating the figure and the axis
fig, ax = plt.subplots()

# Plotting the PDF for each value of lambda
ax.plot(x, expon.pdf(x, scale=1 / lmbda), label=f'λ = {lmbda}')

# Adding title and labels
ax.set_title('Exponential distribution')
ax.set_xlabel('x')
ax.set_ylabel('Probability density')

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)

plt.savefig(f"{directory}/exponential_exp1.{extension}")
plt.close()
35 changes: 35 additions & 0 deletions src/distributions/fisher_f.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import f


def save_to(directory: str, extension: str):
def y(x, dfn, dfd):
y = f.pdf(x, dfn, dfd)
y[y > 2.3] = np.nan
return y

# Degrees of freedom for the distribution
d1_d2 = [(1, 1), (2, 1), (3, 1), (10, 1), (10, 10), (100, 100)]
# Possible values for the distribution
x = np.linspace(0, 5, 1000)

# Creating the figure and the axis
fig, ax = plt.subplots()

# Plotting the PDF for each value of the degrees of freedom
for m, n in d1_d2:
ax.plot(x, y(x, m, n), label=f'm = {m}, n = {n}')

# Adding title and labels
ax.set_title('F-distribution')
ax.set_xlabel('F-statistic')
ax.set_ylabel('Probability density')

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)

plt.savefig(f"{directory}/fisher_f.{extension}")
plt.close()
34 changes: 34 additions & 0 deletions src/distributions/frechet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import invweibull


def save_to(directory: str, extension: str):
def y(x, shape, loc, scale):
return invweibull.pdf(x, shape, loc=loc, scale=scale)
# Inputs for the distribution
inputs = [(0, 1, 1), (1, 1, 1), (0, 0.5, 1), (0, 2, 1), (0, 1, 0.35), (0, 1, 2)]
# x values for the distribution
x = np.linspace(0, 5, 1000)

# Creating the figure and the axis
fig, ax = plt.subplots()

# Plotting the PDF for each value of a
for loc, scale, shape in inputs:
ax.plot(x, y(x, shape, loc, scale), label=f'μ = {loc}, σ = {scale}, α = {shape}')

# Adding title and labels
ax.set_title('Fréchet distribution')
ax.set_xlabel('x')
ax.set_ylabel('Probability density')

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.savefig(f"{directory}/frechet.{extension}")
plt.close()
31 changes: 31 additions & 0 deletions src/distributions/gamma.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gamma


def save_to(directory: str, extension: str):
inputs = [(1, 1), (2, 1), (3, 1), (1, 2), (2, 2), (3, 2)]
# Possible values for the distribution
x = np.linspace(0, 7, 1000)

# Creating the figure and the axis
fig, ax = plt.subplots()
colors = ["blue", "red", "green", "blue", "red", "green"]
alphas = [1.0, 1.0, 1.0, 0.6, 0.6, 0.6]

# Plotting the PDF for each value of alpha and beta
for i, (k, theta) in enumerate(inputs):
ax.plot(x, gamma.pdf(x, k, scale=theta), label=f'k = {k}, θ = {theta}', color=colors[i], alpha=alphas[i])

# Adding title and labels
ax.set_title('Gamma distribution')
ax.set_xlabel('x')
ax.set_ylabel('Probability density')

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)

plt.savefig(f"{directory}/gamma.{extension}")
plt.close()
34 changes: 34 additions & 0 deletions src/distributions/geometric.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import geom


def save_to(directory: str, extension: str):
# Possible values of p for the distribution
p_values = [0.2, 0.5, 0.8]
# Possible outcomes for a Geometric distributed variable
outcomes = np.arange(1, 11)

# Creating the figure and the axis
fig, ax = plt.subplots()
width = 0.2

# Plotting the PMF for each value of p
for i, p in enumerate(p_values):
ax.bar(outcomes + i * width - width, geom.pmf(outcomes, p), width=width, label=f'p = {p}')

# Adding title and labels
ax.set_title('Geometric distribution')
ax.set_xlabel('Number of trials until first success')
ax.set_ylabel('Probability')
ax.set_xticks(outcomes) # set the ticks to be the outcome values

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.savefig(f"{directory}/geometric.{extension}")
plt.close()
31 changes: 31 additions & 0 deletions src/distributions/gumbel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gumbel_r


def save_to(directory: str, extension: str):
inputs = [(0, 1), (0, 0.5), (0, 2), (-2, 1)]
# Possible values for the distribution
x = np.linspace(-5, 5, 1000)

# Creating the figure and the axis
fig, ax = plt.subplots()

# Plotting the PDF for each value of mu and beta
for mu, beta in inputs:
ax.plot(x, gumbel_r.pdf(x, loc=mu, scale=beta), label=f'μ = {mu}, β = {beta}')

# Adding title and labels
ax.set_title('Gumbel distribution')
ax.set_xlabel('x')
ax.set_ylabel('Probability density')

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.savefig(f"{directory}/gumbel.{extension}")
plt.close()
33 changes: 33 additions & 0 deletions src/distributions/hypergeometric.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import hypergeom


def save_to(directory: str, extension: str):
inputs = [(50, 12, 10), (50, 35, 10)]
# Possible outcomes for a Hypergeometric distributed variable
outcomes = np.arange(0, 11)
width = 0.5

# Creating the figure and the axis
fig, ax = plt.subplots()

# Plotting the PMF for each value of N, K, and n
for i, (N, K, n) in enumerate(inputs):
ax.bar(outcomes + i * width - width / 2, hypergeom.pmf(outcomes, N, K, n), width=width, label=f'N = {N}, K = {K}, n = {n}')

# Adding title and labels
ax.set_title('Hypergeometric distribution')
ax.set_xlabel('k (number of successes)')
ax.set_ylabel('Probability')
ax.set_xticks(outcomes) # set the ticks to be the outcome values

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.savefig(f"{directory}/hypergeometric.{extension}")
plt.close()
32 changes: 32 additions & 0 deletions src/distributions/inverse_gaussian.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import invgauss


def save_to(directory: str, extension: str):
# Possible values for the distribution
x = np.linspace(0, 5, 1000)

# Creating the figure and the axis
fig, ax = plt.subplots()

inputs = [(1, 1), (1, 2), (2, 1), (2, 2)]

# Plotting the PDF for the Inverse Gaussian distribution
for mu, lambda_ in inputs:
ax.plot(x, invgauss.pdf(x, mu, scale=lambda_), label=f'μ = {mu}, λ = {lambda_}')

# Adding title and labels
ax.set_title('Inverse Gaussian distribution')
ax.set_xlabel('x')
ax.set_ylabel('Probability density')

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.savefig(f"{directory}/inverse_gaussian.{extension}")
plt.close()
31 changes: 31 additions & 0 deletions src/distributions/log_normal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import lognorm


def save_to(directory: str, extension: str):
inputs = [(0, 1), (0, 0.5), (0, 2), (-0.5, 1), (1, 1)]
# Possible values for the distribution
x = np.linspace(0, 5, 1000)

# Creating the figure and the axis
fig, ax = plt.subplots()

# Plotting the PDF for each value of mu and sigma
for mu, sigma in inputs:
ax.plot(x, lognorm.pdf(x, s=sigma, scale=np.exp(mu)), label=f'μ = {mu}, σ = {sigma}')

# Adding title and labels
ax.set_title('Log-normal distribution')
ax.set_xlabel('x')
ax.set_ylabel('Probability density')

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.savefig(f"{directory}/log_normal.{extension}")
plt.close()
31 changes: 31 additions & 0 deletions src/distributions/normal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm


def save_to(directory: str, extension: str):
inputs = [(0, 1), (0, 0.5), (0, 2), (-2, 1)]
# Possible values for the distribution
x = np.linspace(-5, 5, 1000)

# Creating the figure and the axis
fig, ax = plt.subplots()

# Plotting the PDF for each value of mu and sigma
for mu, sigma in inputs:
ax.plot(x, norm.pdf(x, loc=mu, scale=sigma), label=f'μ = {mu}, σ = {sigma}')

# Adding title and labels
ax.set_title('Normal distribution')
ax.set_xlabel('x')
ax.set_ylabel('Probability density')

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.savefig(f"{directory}/normal.{extension}")
plt.close()
31 changes: 31 additions & 0 deletions src/distributions/normal_inverse_gaussian.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norminvgauss


def save_to(directory: str, extension: str):
inputs = [(1, 0), (3, 0), (0.1, 0), (1, -0.99), (1, 0.99)]
# Possible values for the distribution
x = np.linspace(-5, 5, 1000)

# Creating the figure and the axis
fig, ax = plt.subplots(figsize=(8, 5))

# Plotting the PDF for the Normal Inverse Gaussian distribution
for alpha, beta in inputs:
ax.plot(x, norminvgauss.pdf(x, alpha, beta, 0, 1), label=f'α = {alpha}, β = {beta}')

# Adding title and labels
ax.set_title('Normal Inverse Gaussian distribution')
ax.set_xlabel('x')
ax.set_ylabel('Probability density')

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.savefig(f"{directory}/normal_inverse_gaussian.{extension}")
plt.close()
31 changes: 31 additions & 0 deletions src/distributions/pareto.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import pareto


def save_to(directory: str, extension: str):
inputs = [(1, 1), (1, 2), (1, 3), (2, 1)]
# Possible values for the distribution
x = np.linspace(0, 3, 1000)

# Creating the figure and the axis
fig, ax = plt.subplots()

# Plotting the PDF for each value of alpha
for scale, shape in inputs:
ax.plot(x, pareto.pdf(x, shape, scale=scale), label=f'x$_{{m}}$ = {scale}, α = {shape}')

# Adding title and labels
ax.set_title('Pareto distribution')
ax.set_xlabel('x')
ax.set_ylabel('Probability density')

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.savefig(f"{directory}/pareto.{extension}")
plt.close()
39 changes: 39 additions & 0 deletions src/distributions/pert.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import beta


def save_to(directory: str, extension: str):
def y(x, min_value, mode, max_value, shape):
a = 1 + shape * (mode - min_value) / (max_value - min_value)
b = 1 + shape * (max_value - mode) / (max_value - min_value)
return beta.pdf(x, a, b, loc=min_value, scale=max_value - min_value)

inputs = [(-1, 0, 1, 4), (-1, 0, 1, 1), (-1, 0, 1, 8), (-1, 0.5, 1, 4)]
# Adjusting the range of x values to be more meaningful for the PERT distribution
x = np.linspace(-1, 1, 1000) # max_value in inputs is 2, hence 3 is a reasonable upper bound

# Creating the figure and the axis
fig, ax = plt.subplots(figsize=(10, 5))

# Plotting the PDF for each value of min_value, mode, max_value, and shape
for min_value, mode, max_value, shape in inputs:
ax.plot(x, y(x, min_value, mode, max_value, shape),
label=f'min = {min_value}, mode = {mode}, max = {max_value}, shape = {shape}')

# Adding title and labels
ax.set_title('PERT Distribution')
ax.set_xlabel('x')
ax.set_ylabel('Probability density')

# Adding a legend
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])
ax.legend(loc='upper left', bbox_to_anchor=(1, 1))
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.savefig(f"{directory}/pert.{extension}")
plt.close()
33 changes: 33 additions & 0 deletions src/distributions/poisson.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import poisson


def save_to(directory: str, extension: str):
# Possible values of lambda for the distribution
lambda_values = [0.5, 1, 2, 4, 10]
# Possible outcomes for a Poisson distributed variable
outcomes = np.arange(0, 15)

# Creating the figure and the axis
fig, ax = plt.subplots()

# Plotting the PMF for each value of lambda
for i, lmbda in enumerate(lambda_values):
ax.plot(outcomes, poisson.pmf(outcomes, lmbda), 'o-', label=f'λ = {lmbda}')

# Adding title and labels
ax.set_title('Poisson distribution')
ax.set_xlabel('Outcome')
ax.set_ylabel('Probability')
ax.set_xticks(outcomes) # set the ticks to be the outcome values

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.savefig(f"{directory}/poisson.{extension}")
plt.close()
31 changes: 31 additions & 0 deletions src/distributions/skew_normal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import skewnorm


def save_to(directory: str, extension: str):
inputs = [-5, -2, 0, 2, 5]
# Possible values for the distribution
x = np.linspace(-5, 5, 1000)

# Creating the figure and the axis
fig, ax = plt.subplots()

# Plotting the PDF for each value of alpha
for alpha in inputs:
ax.plot(x, skewnorm.pdf(x, alpha), label=f'α = {alpha}')

# Adding title and labels
ax.set_title('Skew Normal distribution')
ax.set_xlabel('x')
ax.set_ylabel('Probability density')

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.savefig(f"{directory}/skew_normal.{extension}")
plt.close()
30 changes: 30 additions & 0 deletions src/distributions/standard_geometric.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import geom


def save_to(directory: str, extension: str):
# Possible outcomes for a Geometric distributed variable
outcomes = np.arange(1, 11)

# Creating the figure and the axis
fig, ax = plt.subplots()

# Plotting the PMF for the standard Geometric distribution
ax.bar(outcomes, geom.pmf(outcomes, 0.5), label=f'p = 0.5')

# Adding title and labels
ax.set_title('Standard Geometric distribution')
ax.set_xlabel('Number of trials until first success')
ax.set_ylabel('Probability')
ax.set_xticks(outcomes) # set the ticks to be the outcome values

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.savefig(f"{directory}/standard_geometric.{extension}")
plt.close()
29 changes: 29 additions & 0 deletions src/distributions/standard_normal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm


def save_to(directory: str, extension: str):
# Possible values for the distribution
x = np.linspace(-5, 5, 1000)

# Creating the figure and the axis
fig, ax = plt.subplots()

# Plotting the PDF for the standard normal distribution
ax.plot(x, norm.pdf(x), label=f'μ = 0, σ = 1')

# Adding title and labels
ax.set_title('Standard normal distribution')
ax.set_xlabel('x')
ax.set_ylabel('Probability density')

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.savefig(f"{directory}/standard_normal.{extension}")
plt.close()
32 changes: 32 additions & 0 deletions src/distributions/student_t.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import t


def save_to(directory: str, extension: str):
# Degrees of freedom for the distribution
df_values = [0.1, 0.5, 1, 2, 5, np.inf]
# Possible values for the distribution
x = np.linspace(-5, 5, 1000)

# Creating the figure and the axis
fig, ax = plt.subplots()

# Plotting the PDF for each value of the degrees of freedom
for df in df_values:
ax.plot(x, t.pdf(x, df), label=f'nu = {df}')

# Adding title and labels
ax.set_title('T-distribution')
ax.set_xlabel('x')
ax.set_ylabel('Probability density')

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.savefig(f"{directory}/student_t.{extension}")
plt.close()
35 changes: 35 additions & 0 deletions src/distributions/triangular.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import triang


def save_to(directory: str, extension: str):
# Defining the Triangular distribution PDF
def y(a, b, c, x):
return triang.pdf(x, c=(c - a) / (b - a), loc=a, scale=b - a)

inputs = [(0, 1, 0.5), (0, 1, 0.25), (0, 1, 0.75), (-1, 1, 0)]
# Possible values for the distribution
x = np.linspace(-1, 1, 1000)

# Creating the figure and the axis
fig, ax = plt.subplots()

# Plotting the PDF for each value of a, b, and c
for a, b, c in inputs:
ax.plot(x, y(a, b, c, x), label=f'a = {a}, b = {b}, c = {c}')

# Adding title and labels
ax.set_title('Triangular distribution')
ax.set_xlabel('x')
ax.set_ylabel('Probability density')

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.savefig(f"{directory}/triangular.{extension}")
plt.close()
50 changes: 50 additions & 0 deletions src/distributions/unit_ball.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from scipy.spatial import ConvexHull


def save_to(directory: str, extension: str):
# Create a sphere
def plot_sphere(radius=1, num_divisions=50):
phi = np.linspace(0, np.pi, num_divisions) # polar angle
theta = np.linspace(0, 2 * np.pi, num_divisions) # azimuthal angle

# Meshgrid
phi, theta = np.meshgrid(phi, theta)
x = radius * np.sin(phi) * np.cos(theta)
y = radius * np.sin(phi) * np.sin(theta)
z = radius * np.cos(phi)

return x, y, z

# Plotting parameters
radius = 1
num_divisions = 50 # Increase this for a smoother sphere

x, y, z = plot_sphere(radius, num_divisions)

# Create a plot
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(x, y, z, color='b', rstride=1, cstride=1, alpha=0.6, edgecolor='none')

# Scaling the axes
ax.set_xlim([-1, 1])
ax.set_ylim([-1, 1])
ax.set_zlim([-1, 1])
ax.set_aspect('auto')
ax.set_box_aspect([1, 1, 1])

# Labels and title
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('Unit Ball (solid)')
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

# Save the figure
plt.savefig(f"{directory}/unit_ball.{extension}")
plt.close()
42 changes: 42 additions & 0 deletions src/distributions/unit_circle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import numpy as np
import matplotlib.pyplot as plt


def save_to(directory: str, extension: str):
# Create a circle
def plot_circle(radius=1, num_divisions=100):
theta = np.linspace(0, 2 * np.pi, num_divisions)
x = radius * np.cos(theta)
y = radius * np.sin(theta)

return x, y

# Plotting parameters
radius = 1
num_divisions = 100 # Increase this for a smoother circle

x, y = plot_circle(radius, num_divisions)

# Create a plot
fig, ax = plt.subplots(figsize=(8, 8))
ax.plot(x, y, color='b', alpha=0.6)

# Scaling the axes
ax.set_xlim([-1, 1])
ax.set_ylim([-1, 1])
ax.set_aspect('equal')

# Labels and title
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_title('Unit Circle')
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.tight_layout()

# Save the figure
plt.savefig(f"{directory}/unit_circle.{extension}")
plt.close()
42 changes: 42 additions & 0 deletions src/distributions/unit_disc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import numpy as np
import matplotlib.pyplot as plt


def save_to(directory: str, extension: str):
# Create a circle
def plot_circle(radius=1, num_divisions=100):
theta = np.linspace(0, 2 * np.pi, num_divisions)
x = radius * np.cos(theta)
y = radius * np.sin(theta)

return x, y

# Plotting parameters
radius = 1
num_divisions = 100 # Increase this for a smoother circle

x, y = plot_circle(radius, num_divisions)

# Create a plot
fig, ax = plt.subplots(figsize=(8, 8))
ax.fill(x, y, color='b', alpha=0.6)

# Scaling the axes
ax.set_xlim([-1, 1])
ax.set_ylim([-1, 1])
ax.set_aspect('equal')

# Labels and title
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_title('Unit Disc')
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.tight_layout()

# Save the figure
plt.savefig(f"{directory}/unit_disc.{extension}")
plt.close()
48 changes: 48 additions & 0 deletions src/distributions/unit_sphere.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import numpy as np
import matplotlib.pyplot as plt


def save_to(directory: str, extension: str):
# Create a sphere
def plot_sphere(radius=1, num_divisions=50):
phi = np.linspace(0, np.pi, num_divisions) # polar angle
theta = np.linspace(0, 2 * np.pi, num_divisions) # azimuthal angle

# Meshgrid
phi, theta = np.meshgrid(phi, theta)
x = radius * np.sin(phi) * np.cos(theta)
y = radius * np.sin(phi) * np.sin(theta)
z = radius * np.cos(phi)

return x, y, z

# Plotting parameters
radius = 1
num_divisions = 50 # Increase this for a smoother sphere

x, y, z = plot_sphere(radius, num_divisions)

# Create a plot
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, projection='3d')
ax.plot_wireframe(x, y, z, color='b', alpha=0.6, rstride=1, cstride=1)

# Scaling the axes
ax.set_xlim([-1, 1])
ax.set_ylim([-1, 1])
ax.set_zlim([-1, 1])
ax.set_aspect('auto')
ax.set_box_aspect([1, 1, 1])

# Labels and title
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('Unit Sphere (shell)')
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

# Save the figure
plt.savefig(f"{directory}/unit_sphere.{extension}")
plt.close()
36 changes: 36 additions & 0 deletions src/distributions/weibull.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import weibull_min


def save_to(directory: str, extension: str):
def y(x, scale, shape):
y = weibull_min.pdf(x, shape, scale=scale)
y[y > 5] = np.nan
return y
# Possible values of alpha for the distribution
inputs = [(1, 1), (2, 1), (3, 1), (1, 2), (1, 3), (2, 2)]
# Possible values for the distribution
x = np.linspace(0, 3, 1000)

# Creating the figure and the axis
fig, ax = plt.subplots()

# Plotting the PDF for each value of alpha
for scale, shape in inputs:
ax.plot(x, y(x, scale, shape), label=f'λ = {scale}, k = {shape}')

# Adding title and labels
ax.set_title('Weibull distribution')
ax.set_xlabel('x')
ax.set_ylabel('Probability density')

# Adding a legend
ax.legend()
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

plt.savefig(f"{directory}/weibull.{extension}")
plt.close()
30 changes: 30 additions & 0 deletions src/distributions/zeta.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import zipf


def save_to(directory: str, extension: str):
inputs = [3, 2, 1.5, 1.1] # Different values of s and n
outcomes = np.arange(1, 11) # Outcomes from 1 to 10

# Creating the figure
fig, ax = plt.subplots()
width = 0.2 # Bar width

# Plotting the Zipf Distribution for each value of s
for i, s in enumerate(inputs):
ax.bar(outcomes + i * width - width * 3 / 2, zipf.pmf(outcomes, s), width=width, label=f's = {s}')

ax.set_title('Zeta Distribution')
ax.set_xlabel('Outcome')
ax.set_ylabel('Probability')
ax.set_xticks(outcomes) # Adjusting x-ticks to center
ax.legend()
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

# Save the plot to a file
plt.savefig(f"{directory}/zeta.{extension}")
plt.close()
30 changes: 30 additions & 0 deletions src/distributions/zipf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import zipfian


def save_to(directory: str, extension: str):
inputs = [(2, 10), (1, 10), (0, 10)] # Different values of s and n
outcomes = np.arange(1, 12) # Outcomes from 1 to 10

# Creating the figure
fig, ax = plt.subplots()
width = 0.2 # Bar width

# Plotting the Zipf Distribution for each value of s
for i, (s, n) in enumerate(inputs):
ax.bar(outcomes + i * width - width, zipfian.pmf(outcomes, s, n), width=width, label=f's = {s}, n = {n}')

ax.set_title('Zipf Distribution')
ax.set_xlabel('Outcome')
ax.set_ylabel('Probability')
ax.set_xticks(outcomes) # Adjusting x-ticks to center
ax.legend()
ax.grid()
ax.margins(x=0, y=0)
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax * 1.05)

# Save the plot to a file
plt.savefig(f"{directory}/zipf.{extension}")
plt.close()
76 changes: 76 additions & 0 deletions src/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import os
from distributions import (
beta,
binomial,
cauchy,
chi_squared,
dirichlet,
exponential,
exponential_exp1,
fisher_f,
frechet,
gamma,
geometric,
gumbel,
hypergeometric,
inverse_gaussian,
log_normal,
normal,
normal_inverse_gaussian,
pareto,
pert,
poisson,
skew_normal,
standard_geometric,
standard_normal,
student_t,
triangular,
unit_ball,
unit_circle,
unit_disc,
unit_sphere,
weibull,
zeta,
zipf,
)

if __name__ == "__main__":
out = "charts"
ext = "svg"
if not os.path.exists(out):
os.makedirs(out)
for distr in (
beta,
binomial,
cauchy,
chi_squared,
dirichlet,
exponential,
exponential_exp1,
fisher_f,
frechet,
gamma,
geometric,
gumbel,
hypergeometric,
inverse_gaussian,
log_normal,
normal,
normal_inverse_gaussian,
pareto,
pert,
poisson,
skew_normal,
standard_geometric,
standard_normal,
student_t,
triangular,
unit_ball,
unit_circle,
unit_disc,
unit_sphere,
weibull,
zeta,
zipf,
):
distr.save_to(out, ext)