@@ -1190,6 +1190,92 @@ def get_data(self):
11901190 data [impl .name ] = impl .value
11911191 return data
11921192
1193+ def get_vars (self , all_named_ops = False ):
1194+ """
1195+ Get all the variables used in the DataOp.
1196+
1197+ Parameters
1198+ ----------
1199+ all_named_ops : bool, default = False
1200+ If False, return only actual variables (DataOps created with
1201+ :func:`var()`, :func:`X()` or :func:`y()`). If False, return all
1202+ nodes that have a name (ie for which a value can be passed in the
1203+ environment).
1204+
1205+ Returns
1206+ -------
1207+ dict :
1208+ Keys are names, and values the corresponding DataOp.
1209+
1210+ Examples
1211+ --------
1212+ >>> import skrub
1213+
1214+ >>> a = skrub.var("a")
1215+ >>> b = skrub.var("b")
1216+ >>> c = (a + b).skb.set_name("c")
1217+ >>> d = c + c
1218+ >>> d
1219+ <BinOp: add>
1220+
1221+ Our DataOp, `d`, contains 2 variables: "a" and "b":
1222+
1223+ >>> d.skb.get_vars()
1224+ {'a': <Var 'a'>, 'b': <Var 'b'>}
1225+
1226+ Those are the keys for which we need to provide values in the
1227+ environment when evaluating `d`:
1228+
1229+ >>> d.skb.eval({"a": 10, "b": 3}) # (10 + 3) + (10 + 3) = 26
1230+ 26
1231+
1232+ In addition, we set a name on the internal node `c`. It is not a
1233+ variable, and normally it is computed as `(a + b)`. But as it has a
1234+ name, we can override its output by passing a value for "c" in the
1235+ environment. When we do, the computation of `c` never happens (nor of
1236+ `a` or `b`, here, because they are only used to compute `c`) -- it is
1237+ bypassed and the provided value is used instead.
1238+
1239+ >>> d.skb.eval({"c": 7}) # 7 + 7 = 14
1240+ 14
1241+
1242+ If we want ``get_vars`` to also list nodes like our example ``c`` which
1243+ have a name and can be passed in the environment, we pass
1244+ ``all_named_ops=True``:
1245+
1246+ >>> d.skb.get_vars(all_named_ops=True)
1247+ {'a': <Var 'a'>, 'b': <Var 'b'>, 'c': <c | BinOp: add>}
1248+
1249+ Note ``get_vars`` can be particularly useful when we have a learner
1250+ (e.g. loaded from a pickle file) and we want to check what inputs we
1251+ should pass to its methods such as ``fit`` and ``transform``:
1252+
1253+ >>> learner = d.skb.make_learner()
1254+ >>> list(learner.data_op.skb.get_vars().keys())
1255+ ['a', 'b']
1256+
1257+ The output above tells us what keys the dict we pass to
1258+ ``learner.fit()`` should contain:
1259+
1260+ >>> learner.fit({'a': 2, 'b': 3})
1261+ SkrubLearner(data_op=<BinOp: add>)
1262+ """
1263+ from ._data_ops import Var
1264+ from ._evaluation import nodes
1265+
1266+ named_nodes = {
1267+ name : op
1268+ for op in nodes (self ._data_op )
1269+ if (name := op ._skrub_impl .name ) is not None
1270+ }
1271+ if all_named_ops :
1272+ return named_nodes
1273+ return {
1274+ name : op
1275+ for name , op in named_nodes .items ()
1276+ if isinstance (op ._skrub_impl , Var )
1277+ }
1278+
11931279 def draw_graph (self ):
11941280 """Get an SVG string representing the computation graph.
11951281
0 commit comments