Проведите линию по главной оси эллипса уверенности - PullRequest
0 голосов
/ 17 июня 2020

У меня есть два одномерных массива (A и B) равной длины, и я хотел бы построить эллипс уверенности для их распределения рассеяния и провести линию вдоль главной оси этого эллипса уверенности. Я попытался понять коды в этих двух ссылках:

1) https://matplotlib.org/3.1.1/gallery/statistics/confidence_ellipse.html#sphx -glr-gallery-statistics-уверенность-эллипс-py

2) Извлечь координаты, заключенные в патч matplotlib.

Я думаю, что их слияние - это то, что я ищу. То есть построить эллипс уверенности после первой ссылки и найти допустимые координаты внутри эллипса, следующего за второй связью. Если я могу получить все координаты, разрешенные в пределах эллипса уверенности, я могу затем оценить большую ось как максимально возможное расстояние между комбинацией разрешенных координат.

Надеюсь, что приведенный ниже код иллюстрирует то, что я пытаюсь сделать. Но я не совсем понимаю все пути и функции, работающие в этих кодах, поэтому их объединение не является прямым для меня. В настоящее время я получаю сообщение об ошибке «ValueError: требуется хотя бы один массив для объединения», и я полагаю, что это означает, что я не могу определить эллипс, который я хочу сохранить «el», как я это делаю?

I поэтому интересно, может ли кто-нибудь помочь мне с эффективным способом вычисления эллипса уверенности и проведения линии вдоль его главной оси. Заранее спасибо!

# Imports
from matplotlib.patches import Ellipse
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.transforms as transforms
import numpy as np
from scipy.stats.stats import pearsonr
import random


# Creating fake data: Arrays A & B
print('Creating fake data')
A = np.random.randint(11, size=200)
B = np.random.randint(11, size=200)


# Define the "confidence_ellipse" from 1st link:
# https://matplotlib.org/3.1.1/gallery/statistics/confidence_ellipse.html#sphx-glr-gallery-statistics-confidence-ellipse-py
print('Define the "confidence_ellipse" from 1st link')

def confidence_ellipse(x, y, ax, n_std=3.0, facecolor='none', **kwargs):
    """
    Create a plot of the covariance confidence ellipse of `x` and `y`

    Parameters
    ----------
    x, y : array_like, shape (n, ) ;  Input data.

    ax : matplotlib.axes.Axes ;  The axes object to draw the ellipse into.

    n_std : float ;  The number of standard deviations to determine the ellipse's radiuses.

    Returns
    -------
    matplotlib.patches.Ellipse

    Other parameters
    ----------------
    kwargs : `~matplotlib.patches.Patch` properties
    """
    if x.size != y.size:
        raise ValueError("x and y must be the same size")

    cov = np.cov(x, y)
    pearson = cov[0, 1]/np.sqrt(cov[0, 0] * cov[1, 1])
    # Using a special case to obtain the eigenvalues of this two-dimensionl dataset.
    ell_radius_x = np.sqrt(1 + pearson)
    ell_radius_y = np.sqrt(1 - pearson)
    ellipse = Ellipse((0, 0), width=ell_radius_x * 2, height=ell_radius_y * 2, facecolor=facecolor, **kwargs)

    # Calculating the stdandard deviation of x from the squareroot of the variance and multiplying with the given number of standard deviations.
    scale_x = np.sqrt(cov[0, 0]) * n_std
    mean_x = np.mean(x)

    # calculating the stdandard deviation of y ...
    scale_y = np.sqrt(cov[1, 1]) * n_std
    mean_y = np.mean(y)

    transf = transforms.Affine2D() \
        .rotate_deg(45) \
        .scale(scale_x, scale_y) \
        .translate(mean_x, mean_y)

    ellipse.set_transform(transf + ax.transData)
    return ax.add_patch(ellipse)


# Plot Figure to Visualize Confidence Ellipses (following link 1)
print('Plot Figure to Visualize Confidence Ellipses')

fig, ax_nstd = plt.subplots(figsize=(6, 6))

dependency_nstd = np.array([[0.8, 0.75], [-0.2, 0.35]])
mu = 0, 0
scale = 8, 5

ax_nstd.axvline(c='grey', lw=1)
ax_nstd.axhline(c='grey', lw=1)

ax_nstd.scatter(A, B, s=0.5)

confidence_ellipse(A, B, ax_nstd, n_std=1, label=r'$1\sigma$', edgecolor='firebrick')
confidence_ellipse(A, B, ax_nstd, n_std=2, label=r'$2\sigma$', edgecolor='green')
confidence_ellipse(A, B, ax_nstd, n_std=3, label=r'$3\sigma$', edgecolor='blue')

el = confidence_ellipse(A, B, ax_nstd, n_std=1)    # Save the ellipse for 1 std. Use same name for ellipse as in link 2

ax_nstd.scatter(mu[0], mu[1], c='red', s=3)
ax_nstd.set_title('Different standard deviations')

ax_nstd.legend()
ax_nstd.set_xlim([np.min(A), np.max(A)])
ax_nstd.set_ylim([np.min(B), np.max(B)])

plt.show()


# Get All Coordinates Possible Within the CE Confidence Ellipse Following Link 2:
# https://stackoverflow.com/questions/25145931/extract-coordinates-enclosed-by-a-matplotlib-patch
print('Get All Coordinates Possible Within the CE Confidence Ellipse Link 2')

# calculate the x and y points possibly within the ellipse
y_int = np.arange(0, 11)
x_int = np.arange(0, 11)

# create a list of possible coordinates
g = np.meshgrid(x_int, y_int)
coords = list(zip(*(c.flat for c in g)))

# create the list of valid coordinates (from untransformed)
ellipsepoints = np.vstack([p for p in coords if el.contains_point(p, radius=0)])

# Plot All Coordiantes Allowed Within the Confidence Ellipse "el"
fig = plt.figure()
ax = fig.add_subplot(111)
ax.add_artist(el)
ep = np.array(ellipsepoints)
ax.plot(ellipsepoints[:,0], ellipsepoints[:,1], 'ko')
plt.show()
...