def get_mete_rad(S, N, beta=None, beta_dict={}): """Use beta to generate SAD predicted by the METE Keyword arguments: S -- the number of species N -- the total number of individuals beta -- allows input of beta by user if it has already been calculated """ assert S > 1, "S must be greater than 1" assert N > 0, "N must be greater than 0" assert S/N < 1, "N must be greater than S" if beta is None: beta = get_beta(S, N, beta_dict=beta_dict) p = e ** -beta abundance = list(empty([S])) rank = range(1, int(S)+1) rank.reverse() if p >= 1: for i in range(0, int(S)): y = lambda x: trunc_logser_cdf(x, p, N) - (rank[i]-0.5) / S if y(1) > 0: abundance[i] = 1 else: abundance[i] = int(round(bisect(y,1,N))) else: for i in range(0, int(S)): y = lambda x: logser.cdf(x,p) / logser.cdf(N,p) - (rank[i]-0.5) / S abundance[i] = int(round(bisect(y, 0, N))) return (abundance, p)
def trunc_logser_cdf(x_max, p, upper_bound): """Cumulative probability function for the upper truncated log-series""" if p < 1: #If we can just renormalize the untruncated cdf do so for speed return logser.cdf(x_max, p) / logser.cdf(upper_bound, p) else: x_list = range(1, int(x_max) + 1) cdf = sum(trunc_logser_pmf(x_list, p, upper_bound)) return cdf
def trunc_logser_pmf(x, p, upper_bound): """Probability mass function for the upper truncated log-series Parameters ---------- x : array_like Values of `x` for which the pmf should be determined p : float Parameter for the log-series distribution upper_bound : float Upper bound of the distribution Returns ------- pmf : array Probability mass function for each value of `x` """ if p < 1: return logser.pmf(x, p) / logser.cdf(upper_bound, p) else: x = np.array(x) ivals = np.arange(1, upper_bound + 1) normalization = sum(p ** ivals / ivals) pmf = (p ** x / x) / normalization return pmf
def kolmogorov_criterion(self): n = len(self.sample) x, emp_cdf = self.distribution_function() cdf = logser.cdf(x, self.p) d = emp_cdf - cdf d_n = np.amax(np.absolute(d)) s_k = d_n * np.sqrt(n) print('logser', s_k)
def get_mete_rad(S, N, beta=None, version='precise', beta_dict={}): """Use beta to generate RAD predicted by the METE. This function switches between two methods to obtain RAD, one that accounts for p>=1 but can potentially fail for p values close to 1 (previously get_mete_rad()) and one that does not but always works for p<1 (previously get_mete_rad_bigN()). Keyword arguments: S -- the number of species N -- the total number of individuals beta -- allows input of beta by user if it has already been calculated """ assert S > 1, "S must be greater than 1" assert N > 0, "N must be greater than 0" assert S / N < 1, "N must be greater than S" if beta is None: beta = get_beta(S, N, version=version, beta_dict=beta_dict) p = e**-beta abundance = list(empty([S])) rank = range(1, int(S) + 1) if p >= 1: rank.reverse() for i in range(0, int(S)): y = lambda x: trunc_logser_cdf(x, p, N) - (rank[i] - 0.5) / S if y(1) > 0: abundance[i] = 1 else: abundance[i] = int(round(bisect(y, 1, N))) return (abundance, p) else: cdf_obs = [(rank[i] - 0.5) / S for i in range(0, int(S))] cdf_N = logser.cdf(N, p) j = 0 cdf_cum = 0 #Obtain the cdf at each x by manually adding up pmf #instead of using bisect() to avoid calculting cdf #over and over again i = 1 while i <= N + 1: cdf_cum += -1 / log(1 - p) * p**i / i / cdf_N while cdf_cum >= cdf_obs[j]: abundance[j] = i j += 1 if j == S: abundance.reverse() return (abundance, p) i += 1
x = np.arange(logser.ppf(0.01, p), logser.ppf(0.99, p)) ax.plot(x, logser.pmf(x, p), 'bo', ms=8, label='logser pmf') ax.vlines(x, 0, logser.pmf(x, p), colors='b', lw=5, alpha=0.5) # Alternatively, the distribution object can be called (as a function) # to fix the shape and location. This returns a "frozen" RV object holding # the given parameters fixed. # Freeze the distribution and display the frozen ``pmf``: rv = logser(p) ax.vlines(x, 0, rv.pmf(x), colors='k', linestyles='-', lw=1, label='frozen pmf') ax.legend(loc='best', frameon=False) plt.show() # Check accuracy of ``cdf`` and ``ppf``: prob = logser.cdf(x, p) np.allclose(x, logser.ppf(prob, p)) # True # Generate random numbers: r = logser.rvs(p, size=1000)
def theoretical_distribution(self): x = np.array([i for i in range(self.r_low, self.r_up + 1)]) plt.plot(x, logser.cdf(x, self.p), 'ro')