Skip to content

Commit

Permalink
Some linting while re-reading library (#219)
Browse files Browse the repository at this point in the history
  • Loading branch information
camenpihor committed Jul 3, 2020
1 parent 1e2fc0d commit c3fd56c
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 73 deletions.
5 changes: 2 additions & 3 deletions README.md
@@ -1,5 +1,5 @@
Bambi
------
# Bambi

BAyesian Model-Building Interface in Python

[![Build Status](https://travis-ci.org/bambinos/bambi.svg?branch=master)](https://travis-ci.org/bambinos/bambi)
Expand All @@ -26,7 +26,6 @@ Alternatively, if you want the bleeding edge version of the package you can inst

Bambi requires working versions of numpy, pandas, matplotlib, patsy, pymc3, and theano. Dependencies are listed in `requirements.txt`, and should all be installed by the Bambi installer; no further action should be required.


## Documentation

The Bambi documentation can be found in the [official docs](https://bambinos.github.io/bambi/index.html)
Expand Down
4 changes: 1 addition & 3 deletions bambi/backends/__init__.py
@@ -1,6 +1,4 @@
from .pymc import PyMC3BackEnd


__all__ = [
'PyMC3BackEnd'
]
__all__ = ["PyMC3BackEnd"]
4 changes: 1 addition & 3 deletions bambi/backends/base.py
Expand Up @@ -2,10 +2,8 @@


class BackEnd:
"""Base class for BackEnd hierarchy."""

'''
Base class for BackEnd hierarchy.
'''
__metaclass__ = ABCMeta

@abstractmethod
Expand Down
27 changes: 10 additions & 17 deletions bambi/backends/pymc.py
@@ -1,17 +1,15 @@
import numpy as np
import pymc3 as pm
import theano
from arviz import from_pymc3
import pymc3 as pm

from bambi.priors import Prior

from .base import BackEnd


class PyMC3BackEnd(BackEnd):

"""
PyMC3 model-fitting back-end.
"""
"""PyMC3 model-fitting back-end."""

# Available link functions
links = {
Expand All @@ -25,7 +23,6 @@ class PyMC3BackEnd(BackEnd):
dists = {"HalfFlat": pm.Bound(pm.Flat, lower=0)}

def __init__(self):

self.reset()

# Attributes defined elsewhere
Expand All @@ -35,15 +32,13 @@ def __init__(self):
self.advi_params = None # build()

def reset(self):
"""
Reset PyMC3 model and all tracked distributions and parameters.
"""
"""Reset PyMC3 model and all tracked distributions and parameters."""
self.model = pm.Model()
self.mu = None
self.par_groups = {}

def _build_dist(self, spec, label, dist, **kwargs):
""" Build and return a PyMC3 Distribution. """
"""Build and return a PyMC3 Distribution."""
if isinstance(dist, str):
if hasattr(pm, dist):
dist = getattr(pm, dist)
Expand Down Expand Up @@ -77,8 +72,7 @@ def _expand_args(key, value, label):
return dist(label, **kwargs)

def build(self, spec, reset=True): # pylint: disable=arguments-differ
"""
Compile the PyMC3 model from an abstract model specification.
"""Compile the PyMC3 model from an abstract model specification.
Parameters
----------
Expand Down Expand Up @@ -122,8 +116,7 @@ def build(self, spec, reset=True): # pylint: disable=arguments-differ

# pylint: disable=arguments-differ, inconsistent-return-statements
def run(self, start=None, method="mcmc", init="auto", n_init=50000, **kwargs):
"""
Run the PyMC3 MCMC sampler.
"""Run the PyMC3 MCMC sampler.
Parameters
----------
Expand Down Expand Up @@ -168,9 +161,9 @@ def run(self, start=None, method="mcmc", init="auto", n_init=50000, **kwargs):


def _laplace(model):
"""
Fit a model using a laplace approximation. Mainly for pedagogical use. ``mcmc`` and ``advi``
are better approximations
"""Fit a model using a laplace approximation.
Mainly for pedagogical use. ``mcmc`` and ``advi`` are better approximations.
Parameters
----------
Expand Down
14 changes: 8 additions & 6 deletions bambi/external/patsy.py
@@ -1,14 +1,16 @@
import numpy as np
import re
from patsy.util import safe_scalar_isnan

import numpy as np

from patsy import PatsyError
from patsy.util import safe_scalar_isnan


class Custom_NA:
"""
Custom patsy.missing.NAAction class. Similar to patsy drop/raise defaults,
but changes the raised message and logs which rows (if any) are dropped.
See Patsy code/API for NAAction documentation.
"""Custom patsy.missing.NAAction class.
Similar to patsy drop/raise defaults, but changes the raised message and logs which rows (if
any) are dropped. See Patsy code/API for NAAction documentation.
"""

def __init__(self, dropna=False, NA_types=["None", "NaN"]):
Expand Down
47 changes: 15 additions & 32 deletions bambi/models.py
Expand Up @@ -4,23 +4,21 @@
from collections import OrderedDict
from copy import deepcopy

import pandas as pd
import numpy as np
from patsy import dmatrices, dmatrix
import pandas as pd
import pymc3 as pm
import statsmodels.api as sm
from arviz.plots import plot_posterior
import pymc3 as pm

from patsy import dmatrices, dmatrix

from .backends import PyMC3BackEnd
from .external.patsy import Custom_NA
from .priors import PriorFactory, PriorScaler, Prior
from .priors import Prior, PriorFactory, PriorScaler
from .utils import listify
from .backends import PyMC3BackEnd


class Model:
"""
Specification of model class
"""Specification of model class.
Parameters
----------
Expand Down Expand Up @@ -104,9 +102,7 @@ def __init__(
self.built = False # build()

def reset(self):
"""
Reset list of terms and y-variable.
"""
"""Reset list of terms and y-variable."""
self.terms = OrderedDict()
self.y = None
self.backend = None
Expand All @@ -116,7 +112,6 @@ def reset(self):
self.clean_data = None

def _set_backend(self, backend):

backend = backend.lower()

if backend.startswith("pymc"):
Expand All @@ -140,7 +135,6 @@ def build(self, backend=None):
supported. If None, assume that `fit()` has already been called (possibly without
building) and look in self._backend_name.
"""

# retain only the complete cases
n_total = len(self.data.index)
if self.completes:
Expand Down Expand Up @@ -316,7 +310,6 @@ def fit(
backend : str
The name of the BackEnd to use. Currently only 'pymc' backen is supported.
"""

if fixed is not None or random is not None:
self.add(
fixed=fixed,
Expand All @@ -332,7 +325,6 @@ def fit(
if backend is None:
backend = "pymc" if self._backend_name is None else self._backend_name


if run:
if not self.built or backend != self._backend_name:
self.build(backend)
Expand All @@ -351,8 +343,7 @@ def add(
categorical=None,
append=True,
):
"""
Adds one or more terms to the model via an R-like formula syntax.
"""Add one or more terms to the model via an R-like formula syntax.
Parameters
----------
Expand Down Expand Up @@ -385,7 +376,6 @@ def add(
If True, terms are appended to the existing model rather than replacing any
existing terms. This allows formula-based specification of the model in stages.
"""

data = self.data

# Primitive values (floats, strs) can be overwritten with Prior objects
Expand Down Expand Up @@ -446,7 +436,6 @@ def _add(
Runs during Model.build()
"""

# use cleaned data with NAs removed (if user requested)
data = self.clean_data
# alter this pandas flag to avoid false positive SettingWithCopyWarnings
Expand Down Expand Up @@ -613,13 +602,11 @@ def _add_y(self, variable, prior=None, family="gaussian", link=None, *args, **kw
self.built = False

def _match_derived_terms(self, name):
"""
Returns all (random) terms whose named are derived from the
specified string. For example, 'condition|subject' should match the
terms with names '1|subject', 'condition[T.1]|subject', and so on.
Only works for strings with grouping operator ('|').
"""
"""Return all (random) terms whose named are derived from the specified string.
For example, 'condition|subject' should match the terms with names '1|subject',
'condition[T.1]|subject', and so on. Only works for strings with grouping operator ('|').
"""
if "|" not in name:
return None

Expand Down Expand Up @@ -679,7 +666,6 @@ def _set_priors(self, priors=None, fixed=None, random=None, match_derived_names=
Runs during Model.build().
"""

targets = {}

if fixed is not None:
Expand All @@ -705,16 +691,15 @@ def _set_priors(self, priors=None, fixed=None, random=None, match_derived_names=
for name, prior in targets.items():
self.terms[name].prior = prior

# helper function to correctly set default priors, auto_scaling, etc.
def _prepare_prior(self, prior, _type):
"""
"""Helper function to correctly set default priors, auto_scaling, etc.
Parameters
----------
prior : Prior object, or float, or None.
_type : string
accepted values are: 'intercept, 'fixed', or 'random'.
"""

if prior is None and not self.auto_scale:
prior = self.default_priors.get(term=_type + "_flat")

Expand All @@ -736,8 +721,7 @@ def plot_priors(self, var_names=None):
raise ValueError("Cannot plot priors until model is built!")

with pm.Model():
# get priors for fixed fx, separately for each level of each
# predictor
# get priors for fixed fx, separately for each level of each predictor
dists = []
for fixed_term in self.fixed_terms.values():
if var_names is not None and fixed_term.name not in var_names:
Expand Down Expand Up @@ -811,7 +795,6 @@ class Term:
random = False

def __init__(self, name, data, categorical=False, prior=None, constant=None):

self.name = name
self.categorical = categorical
self._reduced_data = None
Expand Down
14 changes: 7 additions & 7 deletions bambi/priors.py
Expand Up @@ -71,7 +71,6 @@ def update(self, **kwargs):
kwargs : dict
Optional keyword arguments to add to prior args.
"""

# Backends expect numpy arrays, so make sure all numeric values are represented as such.
kwargs = {k: (np.array(v) if isinstance(v, (int, float)) else v) for k, v in kwargs.items()}
self.args.update(kwargs)
Expand Down Expand Up @@ -114,7 +113,6 @@ class PriorFactory:
"""

def __init__(self, defaults=None, dists=None, terms=None, families=None):

if defaults is None:
defaults = join(dirname(__file__), "config", "priors.json")

Expand All @@ -138,7 +136,6 @@ def __init__(self, defaults=None, dists=None, terms=None, families=None):
self.families = defaults["families"]

def _get_prior(self, spec, **kwargs):

if isinstance(spec, str):
spec = re.sub(r"^\#", "", spec)
return self._get_prior(self.dists[spec])
Expand Down Expand Up @@ -217,10 +214,13 @@ def __init__(self, model, taylor):

def _get_slope_stats(self, exog, predictor, sigma_corr, full_mod=None, points=4):
"""
Args:
full_mod: statsmodels GLM to replace MLE model. For when 'predictor'
is not in the fixed part of the model.
points: number of points to use for LL approximation.
Parameters
----------
full_mod : statsmodels.genmod.generalized_linear_model.GLM
Statsmodels GLM to replace MLE model. For when 'predictor' is not in the fixed part
of the model.
points : int
Number of points to use for LL approximation.
"""

if full_mod is None:
Expand Down
6 changes: 4 additions & 2 deletions bambi/utils.py
@@ -1,6 +1,8 @@
def listify(obj):
""" Wraps all non-list or tuple objects in a list; provides a simple
way to accept flexible arguments. """
"""Wrap all non-list or tuple objects in a list.
Provides a simple way to accept flexible arguments.
"""
if obj is None:
return []
else:
Expand Down

0 comments on commit c3fd56c

Please sign in to comment.