Python 如何找到椭圆内的点?

Python 如何找到椭圆内的点?,python,matplotlib,statistics,ellipse,Python,Matplotlib,Statistics,Ellipse,我试图在椭圆内找到点。它不是一个“普通”椭圆,实际上它是基于平均值和标准偏差的,这比计算特征值以找到置信区间要容易得多 函数不是我写的这里是源代码 代码如下: import numpy as np import matplotlib.pyplot as plt from matplotlib.patches import Ellipse import matplotlib.transforms as transforms x = np.array([21.5,16.3,13.7,20.0,1

我试图在椭圆内找到点。它不是一个“普通”椭圆,实际上它是基于平均值和标准偏差的,这比计算特征值以找到置信区间要容易得多

函数不是我写的这里是源代码

代码如下:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
import matplotlib.transforms as transforms

x = np.array([21.5,16.3,13.7,20.0,17.4,10.4,16.9,7.0,13.8,15.2,13.8,8.2,18.0,9.4,13.2,7.2,21.2,30.2,13.5,29.8,18.3,20.2,31.1,21.5,29.8,18.0,13.1,24.1,32.5,15.4,16.1,15.0,25.9,3.0,17.0,23.6,17.6,-11.8,22.2,26.6,17.8,20.6,23.0,28.0,25.3,22.1,22.4,16.3,22.0,12.1])
y = np.array([92.4,98.2,97.6,95.9,96.5,92.1,89.6,89.4,89.2,89.4,90.2,86.7,89.5,89.9,90.2,87.6,104.0,87.3,99.4,85.4,92.8,92.0,87.9,96.2,94.1,95.2,95.6,86.3,87.6,89.5,95.0,97.1,93.0,87.8,98.9,98.2,100.1,45.4,92.1,91.6,94.7,93.9,91.4,91.1,95.7,93.8,96.4,94.1,94.0,89.1])

#function obtained from matplotlib documentation
#https://matplotlib.org/devdocs/gallery/statistics/confidence_ellipse.html

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.
    **kwargs
        Forwarded to `~matplotlib.patches.Ellipse`
    Returns
    -------
    matplotlib.patches.Ellipse
    """
    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)


#implementation
fig, ax = plt.subplots(1, 1, figsize=(8, 4))
ax.scatter(x,y,s=5)
ellipse = confidence_ellipse(x,y,ax,n_std=2,edgecolor='red')
plt.show()

之后,我试图找到中心坐标和椭圆内的点,如下所示:

ellipse.get_center()
Out:(0,0)
ellipse.contains_point([21.5,92.4])#first points in x,y arrays
Out:False
ellipse.contains_point([0,0])#get_center() result
Out:False
椭圆绘图工作正常,但我需要椭圆内的每个点坐标。
我做错了什么?我已经检查了类似的问题,但它们也不起作用。

您可以在绘图上绘制所有
x,y
标签

将numpy导入为np
将matplotlib.pyplot作为plt导入
从matplotlib.patches导入椭圆
将matplotlib.transforms作为转换导入
10.4,10.5,10.9,7.7,7.0,7.0,7.0,13.8,13.8,15.2,13.8,15.2,13.8,15.2,13.8,13.8,15.2,13.8,8.2,8.2,10.2,10.2,15.2,13.8,13.8,13.8,15.2,13.2,13.2,13,13.8,13,15.2,13,13,13.8,13.8,15.2,13.2,13,13.2,13,13,13.2,13,13.2,13,13,13.8,13.8,15.2,13,13.2,13,13,15.2,13,13,13.2,13.2,13.2,13,13,13,13.2,13.8,13.8,13,13,13,13,13[2,22.4,16.3,22.0,12.1])
7.6 7 7 7 7 7 7 7 7 7 7 7 7 0 0 0 0 0 0 0 0 0 0 0 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7(表4,94.1,94.0,89.1])
#从matplotlib文档中获取的函数
#https://matplotlib.org/devdocs/gallery/statistics/confidence_ellipse.html
def置信度_椭圆(x,y,ax,n_标准=3.0,facecolor='none',**kwargs):
"""
创建*x*和*y*的协方差置信椭圆图。
参数
----------
x、 y:阵列状,形状(n,)
输入数据。
ax:matplotlib.axes.axes
要绘制椭圆的轴对象。
n_标准:浮动
确定椭圆半径的标准偏差数。
**夸尔斯
转发至`~matplotlib.patches.eliple`
退换商品
-------
matplotlib.patches.Ellipse
"""
如果x.size!=y、 尺寸:
raise VALUE ERROR(“x和y的大小必须相同”)
cov=np.cov(x,y)
pearson=cov[0,1]/np.sqrt(cov[0,0]*cov[1,1])
#用一个特例求出该方程的特征值
#二维数据集。
厄尔半径=np.sqrt(1+pearson)
厄尔半径=np.sqrt(1-皮尔逊)
椭圆=椭圆((0,0),宽度=椭圆半径,高度=椭圆半径,
facecolor=facecolor,**kwargs)
#计算x的标准偏差
#方差和乘法的平方根
#具有给定数量的标准偏差。
标度x=np.sqrt(cov[0,0])*n\U标准
平均值x=np.平均值(x)
#计算y轴的标准偏差。。。
量表y=np.sqrt(cov[1,1])*n\U标准
平均值y=np.平均值(y)
transf=transforms.Affine2D()\
.旋转45度\
.比例(比例x,比例y)\
.翻译(平均值x,平均值y)
椭圆集_变换(transf+ax.transData)
返回ax.add_补丁(椭圆)
#实施
图,ax=plt.子批次(1,1,figsize=(12,8))
最大散射(x,y,s=15)
椭圆=置信度_椭圆(x,y,ax,n_标准=2,edgecolor='red')
#zip成对地连接x和y坐标
对于拉链中的x,y(x,y):
label=f“({x},{y})”
#label=“{.2f}”。格式化(y)#只绘制点的y值
#打印(标签)#如果要打印参考点,请取消注释
plt.注释(标签,#这是文本
(x,y),#这是要标注的点
textcoords=“偏移点”,#如何定位文本
xytext=(0,10),#从文本到点的距离(x,y)
ha='center')#水平对齐可以是左对齐、右对齐或居中对齐
plt.show()

p.S.:您需要相应地调整
xytext
。这正是该
标签
在图中绘制的点

您还可以
打印这些值以供参考。只要把
print(label)
放进去,它就会为你打印所有的积分

(21.5,92.4)
(16.3,98.2)
(13.7,97.6)
(20.0,95.9)
(17.4,96.5)
(10.4,92.1)
(16.9,89.6)
(7.0,89.4)
(13.8,89.2)
(15.2,89.4)
(13.8,90.2)
(8.2,86.7)
(18.0,89.5)
(9.4,89.9)
(13.2,90.2)
(7.2,87.6)
(21.2,104.0)
(30.2,87.3)
(13.5,99.4)
(29.8,85.4)
(18.3,92.8)
(20.2,92.0)
(31.1,87.9)
(21.5,96.2)
(29.8,94.1)
(18.0,95.2)
(13.1,95.6)
(24.1,86.3)
(32.5,87.6)
(15.4,89.5)
(16.1,95.0)
(15.0,97.1)
(25.9,93.0)
(3.0,87.8)
(17.0,98.9)
(23.6,98.2)
(17.6,100.1)
(-11.8,45.4)
(22.2,92.1)
(26.6,91.6)
(17.8,94.7)
(20.6,93.9)
(23.0,91.4)
(28.0,91.1)
(25.3,95.7)
(22.1,93.8)
(22.4,96.4)
(16.3,94.1)
(22.0,94.0)
(12.1,89.1)

置信度椭圆示例函数仅返回用于绘制的对象,包含点仅会告诉您该点是否在椭圆上

您可能想要的是:

import math
class distribution():
    def __init__(self,x,y):
        self.cov  = np.cov(x, y)        
        self.mean = np.matrix( [np.mean(x), np.mean(y)])
    def dist(self, x,y):
        tmp = np.matrix([x,y])
        diff = self.mean - tmp
        dist = diff * np.linalg.inv(self.cov) * diff.T
        return math.sqrt(dist)
    def is_inside(self, x,y,nstd=2.0):
    if (self.dist(x,y) < nstd):
        return True
    else:
        return False
        
返回true

然后,对于所有要点:

points = np.array(list(zip(x, y)))

points_in  = list(filter(lambda p: d.is_inside(p[0],p[1]), points))
points_out =  list(filter(lambda p: not d.is_inside(p[0],p[1]), points))
x_in = [ x[0] for x in points_in] 
y_in = [ x[1] for x in points_in] 

x_out = [ x[0] for x in points_out] 
y_out = [ x[1] for x in points_out] 


fig2, ax2 = plt.subplots(1, 1, figsize=(8, 8))
ax2.scatter(x_in,y_in,s=5, facecolor="green")
ax2.scatter(x_out,y_out, s=5, facecolor="red")
ellipse = confidence_ellipse(x,y,ax2,n_std=2,edgecolor='red') # this presupposes that you still have the confidence_ellipse still defined

plt.show()
您的输出应该如下所示:
红色的点距离超过2个标准差,绿色的点在里面。

谢谢你的代码,但实际上我正在寻找椭圆内部的“过滤”操作。
points = np.array(list(zip(x, y)))

points_in  = list(filter(lambda p: d.is_inside(p[0],p[1]), points))
points_out =  list(filter(lambda p: not d.is_inside(p[0],p[1]), points))
x_in = [ x[0] for x in points_in] 
y_in = [ x[1] for x in points_in] 

x_out = [ x[0] for x in points_out] 
y_out = [ x[1] for x in points_out] 


fig2, ax2 = plt.subplots(1, 1, figsize=(8, 8))
ax2.scatter(x_in,y_in,s=5, facecolor="green")
ax2.scatter(x_out,y_out, s=5, facecolor="red")
ellipse = confidence_ellipse(x,y,ax2,n_std=2,edgecolor='red') # this presupposes that you still have the confidence_ellipse still defined

plt.show()