These operators creates a connection that "pipes" data from the source
g1 into the sink
Both source and sink can either be
Graph or a
PipeOp (or an object that can be automatically converted into a
%>>!% try to automatically match output channels of
g1 to input channels of
g2; this is only possible if either
the number of output channels of
g1 (as given by
g1$output) is equal to the
number of input channels of
g2 (as given by
g1 has only one output channel (i.e.
g1$output has one line), or
g2 has only one input channel, which is a vararg channel (i.e.
g2$input has one line, with
Connections between channels are created in the
order in which they occur in
g1's output channel 1 is connected to
channel 1, channel 2 to 2 etc.
%>>% always creates deep copies of its input arguments, so they cannot be modified by reference afterwards.
To access individual
PipeOps after composition, use the resulting
%>>!%, on the other hand, tries to avoid cloning its first argument: If it is a
Graph, then this
will be modified in-place.
%>>!% fails, then it leaves
g1 in an incompletely modified state. It is therefore usually recommended to use
%>>%, since the very marginal gain of performance from
%>>!% often does not outweigh the risk of either modifying objects by-reference that should not be modified or getting
graphs that are in an incompletely modified state. However,
when creating long
Graphs, chaining with
%>>!% instead of
%>>% can give noticeable performance benefits
%>>% makes a number of
clone()-calls that is quadratic in chain length,
%>>!% only linear.
concat_graphs(g1, g2, in_place = FALSE) is equivalent to
g1 %>>% g2.
concat_graphs(g1, g2, in_place = TRUE) is equivalent to
g1 %>>!% g2.
Both arguments of
%>>% are automatically converted to
as_graph(); this means that objects on either side may be objects
that can be automatically converted to
PipeOps (such as
Filters), or that can
be converted to
Graphs. This means, in particular,
PipeOps or objects convertible to that, because
as_graph() automatically applies
lists. See examples. If the first argument of
%>>!% is not a
it is cloned just as when
%>>% is used;
%>>!% only avoids
clone() if the first argument is a
g1 %>>% g2 concat_graphs(g1, g2, in_place = FALSE) g1 %>>!% g2
o1 = PipeOpScale$new() o2 = PipeOpPCA$new() o3 = PipeOpFeatureUnion$new(2) # The following two are equivalent: pipe1 = o1 %>>% o2 pipe2 = Graph$new()$ add_pipeop(o1)$ add_pipeop(o2)$ add_edge(o1$id, o2$id) # Note automatical gunion() of lists. # The following three are equivalent: graph1 = list(o1, o2) %>>% o3 graph2 = gunion(list(o1, o2)) %>>% o3 graph3 = Graph$new()$ add_pipeop(o1)$ add_pipeop(o2)$ add_pipeop(o3)$ add_edge(o1$id, o3$id, dst_channel = 1)$ add_edge(o2$id, o3$id, dst_channel = 2) pipe1 %>>!% o3 # modify pipe1 in-place #> Graph with 3 PipeOps: #> ID State sccssors prdcssors #> scale <<UNTRAINED>> pca #> pca <<UNTRAINED>> featureunion scale #> featureunion <<UNTRAINED>> pca pipe1 # contains o1, o2, and o3 now. #> Graph with 3 PipeOps: #> ID State sccssors prdcssors #> scale <<UNTRAINED>> pca #> pca <<UNTRAINED>> featureunion scale #> featureunion <<UNTRAINED>> pca o1 %>>!% o2 #> Graph with 2 PipeOps: #> ID State sccssors prdcssors #> scale <<UNTRAINED>> pca #> pca <<UNTRAINED>> scale o1 # not changed, becuase not a Graph. #> PipeOp: <scale> (not trained) #> values: <robust=FALSE> #> Input channels <name [train type, predict type]>: #> input [Task,Task] #> Output channels <name [train type, predict type]>: #> output [Task,Task]