The reproducibility/extensibility goal is a noble one that I applaud (insert emoticon).
The save as Rds approach doesn't get you more than the original ggplot object, however. Here's an example from the help page
> a_plot <- ggplot(linetypes, aes(0, y)) +
+ geom_segment(aes(xend = 5, yend = y, linetype = lty)) +
+ scale_linetype_identity() +
+ geom_text(aes(label = lty), hjust = 0, nudge_y = 0.2) +
+ scale_x_continuous(NULL, breaks = NULL) +
+ scale_y_reverse(NULL, breaks = NULL)
Where you serialize it, you get back
> str(a_plot)
List of 9
$ data :'data.frame': 6 obs. of 2 variables:
..$ y : int [1:6] 1 2 3 4 5 6
..$ lty: Factor w/ 6 levels "dashed","dotdash",..: 5 1 3 2 4 6
$ layers :List of 2
..$ :Classes 'LayerInstance', 'Layer', 'ggproto', 'gg' <ggproto object: Class LayerInstance, Layer, gg>
aes_params: list
compute_aesthetics: function
compute_geom_1: function
compute_geom_2: function
compute_position: function
compute_statistic: function
data: waiver
draw_geom: function
finish_statistics: function
geom: <ggproto object: Class GeomSegment, Geom, gg>
aesthetics: function
default_aes: uneval
draw_group: function
draw_key: function
draw_layer: function
draw_panel: function
extra_params: na.rm
handle_na: function
non_missing_aes: linetype size shape
optional_aes:
parameters: function
required_aes: x y xend yend
setup_data: function
use_defaults: function
super: <ggproto object: Class Geom, gg>
geom_params: list
inherit.aes: TRUE
layer_data: function
map_statistic: function
mapping: uneval
position: <ggproto object: Class PositionIdentity, Position, gg>
compute_layer: function
compute_panel: function
required_aes:
setup_data: function
setup_params: function
super: <ggproto object: Class Position, gg>
print: function
show.legend: NA
stat: <ggproto object: Class StatIdentity, Stat, gg>
aesthetics: function
compute_group: function
compute_layer: function
compute_panel: function
default_aes: uneval
extra_params: na.rm
finish_layer: function
non_missing_aes:
parameters: function
required_aes:
retransform: TRUE
setup_data: function
setup_params: function
super: <ggproto object: Class Stat, gg>
stat_params: list
super: <ggproto object: Class Layer, gg>
..$ :Classes 'LayerInstance', 'Layer', 'ggproto', 'gg' <ggproto object: Class LayerInstance, Layer, gg>
aes_params: list
compute_aesthetics: function
compute_geom_1: function
compute_geom_2: function
compute_position: function
compute_statistic: function
data: waiver
draw_geom: function
finish_statistics: function
geom: <ggproto object: Class GeomText, Geom, gg>
aesthetics: function
default_aes: uneval
draw_group: function
draw_key: function
draw_layer: function
draw_panel: function
extra_params: na.rm
handle_na: function
non_missing_aes:
optional_aes:
parameters: function
required_aes: x y label
setup_data: function
use_defaults: function
super: <ggproto object: Class Geom, gg>
geom_params: list
inherit.aes: TRUE
layer_data: function
map_statistic: function
mapping: uneval
position: <ggproto object: Class PositionNudge, Position, gg>
compute_layer: function
compute_panel: function
required_aes:
setup_data: function
setup_params: function
x: 0
y: 0.2
super: <ggproto object: Class PositionNudge, Position, gg>
print: function
show.legend: NA
stat: <ggproto object: Class StatIdentity, Stat, gg>
aesthetics: function
compute_group: function
compute_layer: function
compute_panel: function
default_aes: uneval
extra_params: na.rm
finish_layer: function
non_missing_aes:
parameters: function
required_aes:
retransform: TRUE
setup_data: function
setup_params: function
super: <ggproto object: Class Stat, gg>
stat_params: list
super: <ggproto object: Class Layer, gg>
$ scales :Classes 'ScalesList', 'ggproto', 'gg' <ggproto object: Class ScalesList, gg>
add: function
clone: function
find: function
get_scales: function
has_scale: function
input: function
n: function
non_position_scales: function
scales: list
super: <ggproto object: Class ScalesList, gg>
$ mapping :List of 2
..$ x: num 0
..$ y: language ~y
.. ..- attr(*, ".Environment")=<environment: R_GlobalEnv>
..- attr(*, "class")= chr "uneval"
$ theme : list()
$ coordinates:Classes 'CoordCartesian', 'Coord', 'ggproto', 'gg' <ggproto object: Class CoordCartesian, Coord, gg>
aspect: function
backtransform_range: function
clip: on
default: TRUE
distance: function
expand: TRUE
is_free: function
is_linear: function
labels: function
limits: list
modify_scales: function
range: function
render_axis_h: function
render_axis_v: function
render_bg: function
render_fg: function
setup_data: function
setup_layout: function
setup_panel_params: function
setup_params: function
transform: function
super: <ggproto object: Class CoordCartesian, Coord, gg>
$ facet :Classes 'FacetNull', 'Facet', 'ggproto', 'gg' <ggproto object: Class FacetNull, Facet, gg>
compute_layout: function
draw_back: function
draw_front: function
draw_labels: function
draw_panels: function
finish_data: function
init_scales: function
map_data: function
params: list
setup_data: function
setup_params: function
shrink: TRUE
train_scales: function
vars: function
super: <ggproto object: Class FacetNull, Facet, gg>
$ plot_env :<environment: R_GlobalEnv>
$ labels :List of 6
..$ x : chr "x"
..$ y : chr "y"
..$ xend : chr "xend"
..$ yend : chr "y"
..$ linetype: chr "lty"
..$ label : chr "lty"
- attr(*, "class")= chr [1:2] "gg" "ggplot"
With which, of course, you can tinker, but can't fully re-factor to your own data and presentation preferences.
Better, I think, is simply to create a package, combining the source data, the ggplot chain, and perhaps the type specimen output, and the user can substitute, inspect and modify to her heart's content.
Plus (here follows personal peeve), the package can include all necessary metadata.