如何从 python/scipy/numpy 等中的阶跃函数中采样?

How to sample from a step function in python/scipy/numpy etc?

如果我有 bin 边缘和每个 bin 的计数,是否有一种简洁的方法可以从这意味着从概率密度函数中抽样?

这是我的意思的一个例子。

bin_edges = [0,2.1,6.3,23.5]
counts = [5,2,10]

概率密度函数是阶跃函数,步长为:

[0,2.1,6.3,23.5]

第一步的概率密度(台阶高度)为5/(17*2.1)。 第二个bin/step的概率密度是2/(17*4.2),第三个step/bin的概率密度是10/(17*17.2)。

如果您落在 bin/step 中,您采样的值是从步骤的 x 值中统一采样的。因此,如果您在第一步中跌倒,则它在 0 和 2.1 之间是统一的。

是否有使用 Python 模块执行此采样的简洁方法?例如使用 scipy/numpy/etc?

您已经给出了答案:

If you fall in a bin/step the value you sample is uniformly sampled from the x-values of the step. So if you fall in the first step it is uniform between 0 and 2.1.

您以 two-step 方式生成示例:

  1. 根据概率质量函数选择一个 bin
  2. 生成在所选 bin 的值范围内均匀分布的样本

下面的函数就是这样做的

def random_sample(bin_edges, counts):
    n_bins = len(counts) # number of bins
    p_bin = counts/np.sum(counts) # probability mass function (pmf) for the bin
    sample_bin = np.random.choice(np.arange(n_bins), p = p_bin) # sample a bin according to the bin pmf

    # now, generate a random variable uniformly distributed within the sampled bin edges
    sample = np.random.uniform(bin_edges[sample_bin], bin_edges[sample_bin + 1]) 
    return sample

为了测试函数,让我们生成多个独立样本并绘制它们的直方图

bin_edges = [0,2.1,6.3,23.5]
counts = [5,2,10]
samples = [random_sample(bin_edges, counts) for _ in range(100000)]

from seaborn import distplot

distplot(samples,bins = 100,kde=False,norm_hist = True, hist_kws=dict(edgecolor="k", linewidth=1))

不出所料,直方图对应随机变量的分布函数

"If I have bin edges and counts for each bin, is there a nice succinct way to sample from the probability density function this implies?"

这正是 scipy.stats.rv_histogram 的情况。

这是一个例子。

首先,生成一些我们可以用于示例的直方图数据。

In [150]: sample = np.random.gamma(6, size=2000)                                                                                                                

In [151]: hist, edges = np.histogram(sample, bins=5)                                                                                                            

In [152]: hist                                                                                                                                                  
Out[152]: array([490, 949, 438, 100,  23])

In [153]: edges                                                                                                                                                 
Out[153]: 
array([ 1.23006474,  4.19769156,  7.16531838, 10.13294519, 13.10057201,
       16.06819883])

使用该数据创建 rv_histogram 的实例。

In [154]: from scipy.stats import rv_histogram                                                                                                                  

In [155]: rv = rv_histogram((hist, edges))                                                                                                                      

rv 生成随机样本,并绘制其直方图。

In [156]: rv_sample = rv.rvs(size=100000)                                                                                                                       

In [157]: plt.hist(rv_sample, bins=50, alpha=0.5, edgecolor='k')