Interfacing with the gRain R package
The gRain package
(link)
is available from CRAN and provides the only implementation of exact inference in R; currently it
only supports discrete Bayesian networks. The main data structure in gRain is the
grain class, which stores a fitted Bayesian network as a list of conditional
probability tables (much like bnlearn's bn.fit objects) and makes it
possible for setEvidence() and querygrain() to perform posterior inference
via belief propagation.
Exporting a fitted Bayesian networks to gRain
bn.fit objects can be exported with the conversion method as.grain().
> library(bnlearn) > > dag = hc(learning.test) > fitted.bnlearn = bn.fit(dag, learning.test) > fitted.grain = as.grain(fitted.bnlearn) > fitted.grain
Independence network: Compiled: TRUE Propagated: FALSE Evidence: FALSE
Only discrete networks can be exported, since gRain does not support networks with other parametric assumptions.
> dag.gbn = hc(gaussian.test) > fitted.gbn = bn.fit(dag.gbn, gaussian.test) > as.grain(fitted.gbn)
## Error: the gRain package only supports discrete networks.
The other important limitation of gRain, compared to bnlearn,
is that it does not allow for conditional probabilities to be NaN. (This happens when
estimating them via maximum likelihood and some parent configurations are not observed in the data.)
In that case as.grain() will give a warning and replace the NaNs with
uniform distributions, much like the Bayesian posterior estimator would.
> fitted.sparse = bn.fit(dag, learning.test[1:10, ]) > as.grain(fitted.sparse)
## Warning in from.bn.fit.to.grain(x): NaN conditional probabilities in D, ## replaced with a uniform distribution.
Independence network: Compiled: TRUE Propagated: FALSE Evidence: FALSE
Importing a network structure from gRain
Importing network structures works in the same way, with a conversion method as.bn.fit().
> fitted.import = as.bn.fit(fitted.grain) > all.equal(fitted.bnlearn, fitted.import)
[1] TRUE
For convenience, bnlearn also provides an as.bn() conversion function
that returns the network structure underlying the grain object as a bn
object.
> dag.import = as.bn(fitted.grain) > all.equal(dag, dag.import)
[1] TRUE
Note that by default as.bn.fit() disregards any evidence that has been set in the grain
object with setEvidence(). So, for instance, setting B equal to b does not
have any effect on the conditional probability table for node B in the returned bn.fit
object.
> library(gRain) > fitted.with.evidence = setEvidence(fitted.grain, node = "B", state = "b") > as.bn.fit(fitted.with.evidence)$B
Parameters of node B (multinomial distribution) Conditional probability table: A B a b c a 0.85611511 0.44491018 0.11492178 b 0.02517986 0.22095808 0.09446450 c 0.11870504 0.33413174 0.79061372
Using the argument including.evidence will modify the conditional probability table to reflect the
evidence in the grain object.
> as.bn.fit(fitted.with.evidence, including.evidence = TRUE)$B
Parameters of node B (multinomial distribution) Conditional probability table: A B a b c a 0 0 0 b 1 1 1 c 0 0 0
Fri Aug 1 22:59:15 2025 with bnlearn
5.1
and R version 4.5.0 (2025-04-11).