Upgrading#
Andrey is in alpha, so a release may rename an argument or change a default. A renamed argument
keeps its former name for one release: the call still works and warns with
andrey.DeprecatedArgumentWarning, which gives the new name. The changelog lists
each release’s renamed arguments, changed defaults, and changed outputs under Breaking.
To find every former name your code passes, turn the warning into an error and run your code or your tests:
import warnings
import andrey
warnings.simplefilter("error", andrey.DeprecatedArgumentWarning)
From 0.11 to 0.12#
Andrey 0.12.0 renames the arguments below, reads a column’s type only from what you declare, and
removes the former names that 0.11 kept for one release. A former name in the table still works in
0.12, with an andrey.DeprecatedArgumentWarning, and stops working in the next release:
Method |
Former name |
Name now |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
environment |
|
|
every method with |
|
none: ignored; declare the column types |
|
|
none: ignored; |
# 0.11
out = andrey.grasp(data, depth=2)
out = andrey.pcmci(series, pc_alpha=0.1)
with andrey.config(num_workers=8):
boot = andrey.bootstrap(andrey.pc, data, n_boot=200)
# 0.12
out = andrey.grasp(data, grasp_depth=2)
out = andrey.pcmci(series, pc1_alpha=0.1)
with andrey.config(n_jobs=8):
boot = andrey.bootstrap(andrey.pc, data, n_resamples=200)
granger no longer fits a cross-validated lasso. It fits each variable on the past tau_max steps
of every variable by least squares and returns the lagged links whose coefficient has a
Benjamini-Hochberg adjusted p-value of at most alpha, 0.05 by default, over all the links
(fdr_method="fdr_bh"; "none" tests each link at alpha); metadata["p_values"] holds the
adjusted p-values. cv is ignored, with the warning.
pcmci keeps a link when its Benjamini-Hochberg adjusted p-value over all the links is at most
alpha (fdr_method="fdr_bh", the default), so it returns fewer links than in 0.11, mostly the
false ones. fdr_method="none" returns the links of 0.11.
A bootstrap result counts its fits as n_resamples too: BootstrapOutput.n_boot still works for
one release, but the key bootstrap.n_boot of andrey bootstrap --json is now
bootstrap.n_resamples, with no former name.
Former names from 0.10#
The former names that 0.11 kept for one release stopped working in 0.12. A call that passes one
raises TypeError, as it does for any argument the method does not take, such as
andrey.ges(data, lambda_value=2.0), and the message gives the current name:
pcmciplus() got an unexpected keyword argument 'pc_alpha'; it was renamed `alpha` in 0.11.0
A former score name, such as "local_score_BIC", raises ValueError, which lists the scores that
work and gives the current one. andrey run and andrey bootstrap refuse the former
--data-groups and --data-list flags, which are --data now, and the former key=value names
the same way. The table gives the current name of each, and the section From 0.10 to 0.11 below
shows the common calls:
Method |
Former name |
Name now |
|---|---|---|
|
|
|
|
|
none: it set nothing |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
none: the labels come from a DataFrame’s columns |
The bootstrap’s averaged graph#
andrey.bootstrap builds its averaged graph from each pair’s most frequent state, no edge counted
as one, and then makes it a valid graph of the method’s kind, so structure can differ from 0.11’s.
threshold takes values from 0.5 to 1: a pair must be adjacent in more than that share of the
fits, or in all of them. When no valid graph of the kind holds the vote, structure is the resample
graph nearest the others among the resamples that are valid graphs of the kind, with a warning, and
metadata["averaged_graph"] is "nearest_resample" ("nearest_resample_invalid" when no resample
is valid either); strict=True raises instead. frequency and table do not change, so read the
weaker edges there:
# 0.11
boot = andrey.bootstrap(andrey.pc, data, threshold=0.3)
# 0.12
boot = andrey.bootstrap(andrey.pc, data)
weak = [row for row in boot.table() if row["frequency"] > 0.3]
Column types#
A mixed-data test or score you name, such as indep_test="cond_gauss", read every column of at
most max_categories distinct whole numbers as categorical. It now reads only the columns you
declare, with categorical or a DataFrame’s category, bool, or text type, as None does, and
warns about the others that they may hold category codes. Name such columns to keep the former
result:
# 0.11: column "smoker" holds 0 and 1, read as categorical from its values
out = andrey.pc(df, indep_test="cond_gauss")
# 0.12
out = andrey.pc(df, indep_test="cond_gauss", categorical=["smoker"])
out = andrey.pc(df.astype({"smoker": "category"})) # None picks cond_gauss from the type
A test or score for continuous data, such as "fisherz" or "bic", raises ValueError on a
column you declare categorical, by its type as well as by categorical. Leave the setting as None
to pick one that reads categories, or pass categorical=[] to read every column as numbers.
ebic_gamma takes values from 0 to 1 and only with score_func="bic"; drop it from a call with
another score.
Markov-blanket methods#
Without a target, iamb and inter_iamb return a CPDAG, kind cpdag, where they returned the
moral graph, an undirected graph. Pass structure="moral" for the 0.11 graph. mmpc returns the
skeleton, as before, and a CPDAG with structure="cpdag". A call with a target does not change:
# 0.11
moral = andrey.iamb(data) # also inter_iamb
skeleton = andrey.mmpc(data)
# 0.12
moral = andrey.iamb(data, structure="moral")
skeleton = andrey.mmpc(data) # unchanged
cpdag = andrey.iamb(data) # the default: spouse links pruned, colliders and Meek's rules
cpdag = andrey.mmpc(data, structure="cpdag")
From 0.10 to 0.11#
Andrey 0.11.0 gives each setting one name in every method, such as seed, alpha,
penalty_discount, and tau_max, and gives the scores short names. The tables in the changelog’s
0.11.0 section list every renamed argument and value, changed default, and changed output; the
common calls are below. The 0.10 names kept working in 0.11 with a warning and stopped working in
0.12, so a call that upgrades from 0.10 to 0.12 uses the 0.11 names.
Significance level and test#
pc keeps alpha, and pcmci, pcmciplus, lpcmci, and rcd take it too. indep_test=None,
the default, picks the test from the column types you declare, with categorical or a DataFrame’s
category, bool, or text columns, and metadata["indep_test"] names the test the fit used:
# 0.10
out = andrey.pc(df, alpha=0.01) # fisherz, whatever the column types
out = andrey.pcmci(series, alpha_level=0.05)
# 0.11
out = andrey.pc(df, alpha=0.01) # gsq when every column is categorical, cond_gauss when some are
out = andrey.pc(df, alpha=0.01, indep_test="fisherz") # the test of 0.10
out.metadata["indep_test"]
out = andrey.pcmci(series, alpha=0.05)
pcmciplus and lpcmci take alpha for pc_alpha, and rcd for ind_alpha.
Score searches#
lambda_value is penalty_discount, and each score has a short name: "bic", "discrete_bic",
"bdeu", "cond_gauss", and "degen_gauss". On continuous data, the score searches add the
extended-BIC term, ebic_gamma=1.0, so their graphs keep fewer false edges; ebic_gamma=0.0 gives
the graphs of 0.10:
# 0.10
out = andrey.ges(data, score_func="local_score_BIC", lambda_value=2.0)
# 0.11
out = andrey.ges(data, score_func="bic", penalty_discount=2.0)
out = andrey.ges(data, score_func="bic", penalty_discount=2.0, ebic_gamma=0.0) # as in 0.10
Seeds#
# 0.10
out = andrey.ica_lingam(data, random_state=0)
# 0.11
out = andrey.ica_lingam(data, seed=0)
direct_lingam and multi_group_direct_lingam ignored their random_state, and now refuse it;
drop it.
Lags#
granger and longitudinal_lingam take tau_max, the largest lag, as pcmci, pcmciplus, and
lpcmci do, and granger’s default is 1, as theirs is, where maxlag defaulted to 2:
# 0.10
out = andrey.granger(series, maxlag=2)
# 0.11
out = andrey.granger(series, tau_max=2)
longitudinal_lingam and multi_group_direct_lingam take their list of datasets as data, for
data_list and data_groups.
Workers#
andrey.bootstrap runs its fits on the workers andrey.config sets, as every method does, and
takes no num_workers; the variable ANDREY_NUM_WORKERS sets them too:
# 0.11 pre-release builds
boot = andrey.bootstrap(andrey.pc, data, num_workers=8)
# 0.11
with andrey.config(num_workers=8):
boot = andrey.bootstrap(andrey.pc, data)