Skip to content

Commit

Permalink
ruff format
Browse files Browse the repository at this point in the history
  • Loading branch information
vincentarelbundock committed Dec 22, 2023
1 parent 21a1642 commit 6188c40
Show file tree
Hide file tree
Showing 25 changed files with 336 additions and 252 deletions.
8 changes: 0 additions & 8 deletions marginaleffects/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +0,0 @@
from .comparisons import avg_comparisons, comparisons
from .datagrid import datagrid, datagridcf
from .hypotheses import hypotheses
from .plot_comparisons import plot_comparisons
from .plot_predictions import plot_predictions
from .plot_slopes import plot_slopes
from .predictions import avg_predictions, predictions
from .slopes import avg_slopes, slopes
10 changes: 6 additions & 4 deletions marginaleffects/by.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@


def get_by(model, estimand, newdata, by=None, wts=None):

# for predictions
if isinstance(by, list) and len(by) == 1 and by[0] == "group" and "group" not in estimand.columns:
if (
isinstance(by, list)
and len(by) == 1
and by[0] == "group"
and "group" not in estimand.columns
):
by = True

if by is True:
Expand All @@ -20,12 +24,10 @@ def get_by(model, estimand, newdata, by=None, wts=None):
else:
out = pl.DataFrame({"estimate": estimand["estimate"]})


by = [x for x in by if x in out.columns]
if isinstance(by, list) and len(by) == 0:
return out


if wts is None:
out = out.groupby(by, maintain_order=True).agg(pl.col("estimate").mean())
else:
Expand Down
4 changes: 2 additions & 2 deletions marginaleffects/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def __str__(self):
"std_error": "Std.Error",
"statistic": "z",
"p_value": "P(>|z|)",
"s_value": "S"
"s_value": "S",
}

if hasattr(self, "conf_level"):
Expand All @@ -49,7 +49,7 @@ def __str__(self):
valid = list(mapping.keys())

valid = self.datagrid_explicit + valid

valid = [x for x in valid if x in self.columns]
mapping = {key: mapping[key] for key in mapping if key in valid}
tmp = self.select(valid).rename(mapping)
Expand Down
17 changes: 11 additions & 6 deletions marginaleffects/comparisons.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@
from .estimands import estimands
from .getters import get_coef, get_modeldata, get_predict
from .hypothesis import get_hypothesis
from .sanity import (sanitize_by, sanitize_hypothesis_null, sanitize_newdata,
sanitize_variables, sanitize_vcov)
from .sanity import (
sanitize_by,
sanitize_hypothesis_null,
sanitize_newdata,
sanitize_variables,
sanitize_vcov,
)
from .transform import get_transform
from .uncertainty import get_jacobian, get_se, get_z_p_ci
from .utils import get_pad, sort_columns, upcast
Expand Down Expand Up @@ -190,9 +195,7 @@ def inner(coefs, by, hypothesis, wts, nd):

# estimates
tmp = [
get_predict(model, get_coef(model), nd_X).rename(
{"estimate": "predicted"}
),
get_predict(model, get_coef(model), nd_X).rename({"estimate": "predicted"}),
get_predict(model, coefs, lo_X)
.rename({"estimate": "predicted_lo"})
.select("predicted_lo"),
Expand Down Expand Up @@ -270,7 +273,9 @@ def outer(x):
J = get_jacobian(func=outer, coefs=get_coef(model))
se = get_se(J, V)
out = out.with_columns(pl.Series(se).alias("std_error"))
out = get_z_p_ci(out, model, conf_level=conf_level, hypothesis_null=hypothesis_null)
out = get_z_p_ci(
out, model, conf_level=conf_level, hypothesis_null=hypothesis_null
)

out = get_transform(out, transform=transform)
out = get_equivalence(out, equivalence=equivalence, df=np.inf)
Expand Down
15 changes: 8 additions & 7 deletions marginaleffects/datagrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def datagrid(
newdata=None,
FUN_numeric=lambda x: x.mean(),
FUN_other=lambda x: x.mode()[0], # mode can return multiple values
**kwargs
**kwargs,
):
"""
Data grids
Expand Down Expand Up @@ -95,7 +95,6 @@ def datagrid(
return out



def datagridcf(model=None, newdata=None, **kwargs):
"""
Data grids
Expand All @@ -122,20 +121,22 @@ def datagridcf(model=None, newdata=None, **kwargs):
newdata = get_modeldata(model)

if "rowid" not in newdata.columns:
newdata = newdata.with_columns(pl.Series(range(newdata.shape[0])).alias("rowid"))
newdata = newdata.rename({"rowid" : "rowidcf"})
newdata = newdata.with_columns(
pl.Series(range(newdata.shape[0])).alias("rowid")
)
newdata = newdata.rename({"rowid": "rowidcf"})

# Create dataframe from kwargs
dfs = [pl.DataFrame({k: v}) for k, v in kwargs.items()]

# Perform cross join
df_cross = reduce(lambda df1, df2: df1.join(df2, how='cross'), dfs)
df_cross = reduce(lambda df1, df2: df1.join(df2, how="cross"), dfs)

# Drop would-be duplicates
newdata = newdata.drop(df_cross.columns)

result = newdata.join(df_cross, how = "cross")
result = newdata.join(df_cross, how="cross")

result.datagrid_explicit = list(kwargs.keys())

return result
return result
2 changes: 1 addition & 1 deletion marginaleffects/estimands.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def prep(x):
"dydxavg": lambda hi, lo, eps, x, y, w: prep(((hi - lo) / eps).mean()),
"eyexavg": lambda hi, lo, eps, x, y, w: prep(((hi - lo) / eps * (x / y)).mean()),
"eydxavg": lambda hi, lo, eps, x, y, w: prep((((hi - lo) / eps) / y).mean()),
"dyexavg": lambda hi, lo, eps, x, y, w: prep(((((hi - lo) / eps) * x)).mean()),
"dyexavg": lambda hi, lo, eps, x, y, w: prep((((hi - lo) / eps) * x).mean()),
"dydxavgwts": lambda hi, lo, eps, x, y, w: prep(
(((hi - lo) / eps) * w).sum() / w.sum()
),
Expand Down
9 changes: 5 additions & 4 deletions marginaleffects/getters.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ def get_coef(model):


def get_vcov(model, vcov=True):

if isinstance(vcov, bool):
if vcov is True:
V = model.cov_params()
Expand All @@ -37,8 +36,10 @@ def get_vcov(model, vcov=True):
raise ValueError(f"The model object has no {lab} attribute.")

else:
raise ValueError('`vcov` must be a boolean or a string like "HC3", which corresponds to an attribute of the model object such as "vcov_HC3".')

raise ValueError(
'`vcov` must be a boolean or a string like "HC3", which corresponds to an attribute of the model object such as "vcov_HC3".'
)

V = np.array(V)

return V
Expand Down Expand Up @@ -87,4 +88,4 @@ def get_predict(model, params, newdata: pl.DataFrame):
"The `predict()` method must return an array with 1 or 2 dimensions."
)
p = p.with_columns(pl.col("rowid").cast(pl.Int32))
return p
return p
49 changes: 25 additions & 24 deletions marginaleffects/hypotheses.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import numpy as np
import polars as pl

from .classes import MarginaleffectsDataFrame
Expand All @@ -13,27 +12,27 @@
def hypotheses(model, hypothesis=None, conf_level=0.95, vcov=True, equivalence=None):
"""
(Non-)Linear Tests for Null Hypotheses, Joint Hypotheses, Equivalence, Non Superiority, and Non Inferiority.
This function calculates uncertainty estimates as first-order approximate standard errors for linear or non-linear
functions of a vector of random variables with known or estimated covariance matrix. It emulates the behavior of
the excellent and well-established `car::deltaMethod` and `car::linearHypothesis` functions in R, but it supports
more models; requires fewer dependencies; expands the range of tests to equivalence and superiority/inferiority;
This function calculates uncertainty estimates as first-order approximate standard errors for linear or non-linear
functions of a vector of random variables with known or estimated covariance matrix. It emulates the behavior of
the excellent and well-established `car::deltaMethod` and `car::linearHypothesis` functions in R, but it supports
more models; requires fewer dependencies; expands the range of tests to equivalence and superiority/inferiority;
and offers convenience features like robust standard errors.
To learn more, visit the package website: <https://marginaleffects.com/>
Warning #1: Tests are conducted directly on the scale defined by the `type` argument. For some models, it can make
sense to conduct hypothesis or equivalence tests on the `"link"` scale instead of the `"response"` scale which is
Warning #1: Tests are conducted directly on the scale defined by the `type` argument. For some models, it can make
sense to conduct hypothesis or equivalence tests on the `"link"` scale instead of the `"response"` scale which is
often the default.
Warning #2: For hypothesis tests on objects produced by the `marginaleffects` package, it is safer to use the
`hypothesis` argument of the original function. Using `hypotheses()` may not work in certain environments, in lists,
Warning #2: For hypothesis tests on objects produced by the `marginaleffects` package, it is safer to use the
`hypothesis` argument of the original function. Using `hypotheses()` may not work in certain environments, in lists,
or when working programmatically with *apply style functions.
Warning #3: The tests assume that the `hypothesis` expression is (approximately) normally distributed, which for
non-linear functions of the parameters may not be realistic. More reliable confidence intervals can be obtained using
Warning #3: The tests assume that the `hypothesis` expression is (approximately) normally distributed, which for
non-linear functions of the parameters may not be realistic. More reliable confidence intervals can be obtained using
the `inferences()` function with `method = "boot"`.
Parameters:
model : object
Model object estimated by `statsmodels`
Expand All @@ -45,28 +44,28 @@ def hypotheses(model, hypothesis=None, conf_level=0.95, vcov=True, equivalence=N
Whether to use the covariance matrix in the hypothesis test. Default is True.
equivalence : tuple, optional
The equivalence range for the hypothesis test. Default is None.
Returns:
MarginaleffectsDataFrame
A DataFrame containing the results of the hypothesis tests.
Examples:
# When `hypothesis` is `None`, `hypotheses()` returns a DataFrame of parameters
hypotheses(model)
# A different null hypothesis
hypotheses(model, hypothesis = 3)
# Test of equality between coefficients
hypotheses(model, hypothesis="param1 = param2")
# Non-linear function
hypotheses(model, hypothesis="exp(param1 + param2) = 0.1")
# Robust standard errors
hypotheses(model, hypothesis="param1 = param2", vcov="HC3")
# Equivalence, non-inferiority, and non-superiority tests
hypotheses(model, equivalence=(0, 10))
"""
Expand All @@ -86,7 +85,9 @@ def fun(x):
J = get_jacobian(fun, get_coef(model))
se = get_se(J, V)
out = out.with_columns(pl.Series(se).alias("std_error"))
out = get_z_p_ci(out, model, conf_level=conf_level, hypothesis_null=hypothesis_null)
out = get_z_p_ci(
out, model, conf_level=conf_level, hypothesis_null=hypothesis_null
)
out = get_equivalence(out, equivalence=equivalence)
out = sort_columns(out, by=None)
out = MarginaleffectsDataFrame(out, conf_level=conf_level)
Expand Down
1 change: 0 additions & 1 deletion marginaleffects/hypothesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ def get_hypothesis(x, hypothesis):
elif hypothesis == "revpairwise":
hypmat = lincom_revpairwise(x)
else:

raise ValueError(msg)
out = lincom_multiply(x, hypmat.to_numpy())
out = out.with_columns(pl.Series(hypothesis.columns).alias("term"))
Expand Down
Loading

0 comments on commit 6188c40

Please sign in to comment.