如何选择曲线下方的点?

1 投票
2 回答
2796 浏览
提问于 2025-04-17 14:00

我想做的是画一个高斯函数的图。然后在一个范围内随机选一些数字,比如说y的范围是[0,1](因为它是归一化的),x的范围是[0,200]。接着,我想忽略所有在曲线之上的值,只保留曲线下面的值。

   import numpy
   import random
   import math
   import matplotlib.pyplot as plt
   import matplotlib.mlab as mlab
   from math import sqrt
   from numpy import zeros
   from numpy import numarray

   variance = input("Input variance of the star:")
   mean = input("Input mean of the star:")

   x=numpy.linspace(0,200,1000)
   sigma = sqrt(variance)

   z = max(mlab.normpdf(x,mean,sigma))
   foo = (mlab.normpdf(x,mean,sigma))/z
   plt.plot(x,foo)

   zing = random.random()
   random = random.uniform(0,200)

   import random

   def method2(size):
       ret = set()
       while len(ret) < size:
           ret.add((random.random(), random.uniform(0,200)))
       return ret

   size = input("Input number of simulations:")

   foos = set(foo)
   xx = set(x)

   method = method2(size)

   def undercurve(xx,foos,method):
       Upper = numpy.where(foos<(method))
       Lower = numpy.where(foos[Upper]>(method[Upper]))
       return (xx[Upper])[Lower],(foos[Upper])[Lower]

当我尝试打印出曲线下的值时,我遇到了一个错误:

    TypeError: 'set' object has no attribute '__getitem__'

我不知道该怎么修复这个错误。

大家可以看到,我在python和编程方面都很新手,但任何帮助都非常感谢,如果有问题我会尽量回答。

2 个回答

2

你的代码看起来很难懂。不过,你不能用 [] 来访问集合,比如 foos[Upper]method[Upper] 这些都是不合法的。我不明白你为什么要把 foox 转换成集合。此外,假设通过 method2 生成了一个点,比如 (x0, y0),那么 x0 很可能在 x 中是不存在的。

我对 numpy 不太熟悉,但为了你提到的目的,我会这样做:

def undercurve(size):
    result = []
    for i in xrange(size):
        x = random()
        y = random()
        if y < scipy.stats.norm(0, 200).pdf(x): # here's the 'undercurve'
        result.append((x, y))
    return results
3

你看到的错误直接原因大概是这一行(具体的错误信息可以通过完整的追踪信息找到——通常把这个信息贴出来会很有帮助):

Lower = numpy.where(foos[Upper]>(method[Upper]))

因为这个名字让人困惑的变量 method 实际上是一个 set(集合),这是你函数 method2 返回的结果。其实,仔细想想,foos 也是一个 set,所以可能是先在这个上面出问题了。集合不支持用类似 the_set[index] 的方式来索引;这就是关于 __getitem__ 的错误提示是什么意思。

我不太确定你代码中的每个部分是想干什么;像“foos”这样的变量名并没有提供太多帮助。所以我来给你一个可能的解决方案:

# generate sample points
num_pts = 500
sample_xs = np.random.uniform(0, 200, size=num_pts)
sample_ys = np.random.uniform(0, 1, size=num_pts)

# define distribution
mean = 50
sigma = 10

# figure out "normalized" pdf vals at sample points
max_pdf = mlab.normpdf(mean, mean, sigma)
sample_pdf_vals = mlab.normpdf(sample_xs, mean, sigma) / max_pdf

# which ones are under the curve?
under_curve = sample_ys < sample_pdf_vals

# get pdf vals to plot
x = np.linspace(0, 200, 1000)
pdf_vals = mlab.normpdf(x, mean, sigma) / max_pdf

# plot the samples and the curve
colors = np.array(['cyan' if b else 'red' for b in under_curve])
scatter(sample_xs, sample_ys, c=colors)
plot(x, pdf_vals)

当然,你也应该明白,如果你只想要曲线下的点,这其实等同于(但效率要低得多)从正态分布中取样,然后随机选择一个 y 值,范围是从 0 到那个点的 pdf 值:

sample_xs = np.random.normal(mean, sigma, size=num_pts)
max_pdf = mlab.normpdf(mean, mean, sigma)
sample_pdf_vals = mlab.normpdf(sample_xs, mean, sigma) / max_pdf
sample_ys = np.array([np.random.uniform(0, pdf_val) for pdf_val in sample_pdf_vals])

撰写回答