{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Why `paramnormal` ?\n", "### The currect state of the ecosystem", "\n", "Both in `numpy` and `scipy.stats` and in the field of statistics in general, you can refer to the *location* (`loc`) and scale (`scale`) parameters of a distribution. Roughly speaking, they refer to the position and spread of the distribution, respectively. For normal distribtions `loc` refers the mean (symbolized as $\\mu$) and `scale` refers to the standard deviation (a.k.a. $\\sigma$).\n", "\n", "The main problem that `paramnormal` is trying to solve is that sometimes, creating a probability distribution using these parameters (and others) in `scipy.stats` can be confusing. Also the parameters in `numpy.random` can be inconsistently named (admittedly, just a minor inconvenience). " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import numpy as np\n", "from scipy import stats" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Consider the lognormal distribution. \n", "\n", "> In probability theory, a log-normal (or lognormal) distribution is a continuous probability distribution of a random variable whose logarithm is normally distributed. Thus, if the random variable $X$ is log-normally distributed, then $Y = \\ln(X)$ has a normal distribution. Likewise, if $Y$ has a normal distribution, then $X = \\exp(Y)$ has a log-normal distribution. [(from wikipedia)](https://en.wikipedia.org/wiki/Log-normal_distribution)\n", "\n", "\n", "In numpy, you specify the \"mean\" and \"sigma\" of the underlying normal distribution. A lot lof scientific programmers know what that would mean. But `mean` and `standard_deviation`, `loc` and `scale` or `mu` and `sigma` would have been better choices.\n", "\n", "Still, generating random numbers is pretty straight-forward:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "np.random.seed(0)\n", "mu = 0\n", "sigma = 1\n", "N = 3\n", "np.random.lognormal(mean=mu, sigma=sigma, size=N)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In scipy, you need an additional shape parameter (`s`), plus the usual `loc` and `scale`. Aside from the mystery behind what `s` might bem that seems straight-forward enough.\n", "\n", "Except it's not.\n", "\n", "That shape parameter is actually the standard deviation ($\\sigma$) of the underlying normal distribution. The `scale` should be set to the exponentiated location parameter of the raw distribution ($e ^ \\mu$). Finally, `loc` actually refers to a sort of offset that can be applied to entire distribution. In other words, you can translate the distribution up and down to e.g., negative values.\n", "\n", "In my field (civil/environmental engineering) variables that are often assumed to be lognormally distributed (e.g., pollutant concentration) can never have values less than or equal to zerlo. So in that sense, the `loc` parameter in scipy's lognormal distribution **nearly always should be set to zero**.\n", "\n", "With that out of the way, recreating the three numbers above in scipy is done as follows: " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "np.random.seed(0)\n", "stats.lognorm(sigma, loc=0, scale=np.exp(mu)).rvs(size=N)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### A new challenger appears\n", "\n", "\n", "`paramnormal` really just hopes to take away some of this friction. Consider the following:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import paramnormal\n", "\n", "np.random.seed(0)\n", "paramnormal.lognormal(mu=mu, sigma=sigma).rvs(size=N)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Hopefully that's much more readable and straight-forward." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Greek-letter support\n", "\n", "Tom Augspurger added a [lovely little decorator](https://github.com/phobson/paramnormal/commit/b859e601f7ef45acc1d90b5e8cbf14028c715bf1#diff-9486966ced6b55cf6eb6d3aac274249eR14) to let you use greek letters in the function signature." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "np.random.seed(0)\n", "paramnormal.lognormal(μ=mu, σ=sigma).rvs(size=N)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Other distributions \n", "As of now, we provide a convenient interface for the following distributions in `scipy.stats`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "for d in paramnormal.dist.__all__:\n", " print(d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Feel free to submit a pull request at [Github](https://github.com/phobson/paramnormal) to add new distributions." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.1" } }, "nbformat": 4, "nbformat_minor": 0 }