You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The function testGGPlot() tests whether a (student) generated ggplot2 plot is equal to an expected one, but many graphics in R are made with either the package lattice or the (core) package graphics. That means that some sort of support for these graphics needs to be provided, especially since visualization has become so important nowadays.
Support for lattice graphics
A test function for a lattice plot could be perhaps be a straightforward generalization of testGGPlot() because lattice graphics make use of the grid system, just as ggplot2 does. That means that lattice makes a graphical object, or grob, that contains all the features/settings of the plot in the same way as ggplot2 does. Now, I have personally not yet had the time to find out all the details of the testGGPlot() function, but if it compares the generated grob with the expected grob, then the same thing could be done for lattice graphics: create a test function which compares the generated grob with the expected one. See Chapter 6 en Chapter 7 in Murrell, Paul (2019) R Graphics. Third Edition for more information on graphical objects in the grid system.
Support for base graphics
For "base" graphics made with the graphics package, things are not so easy since no graphical object is made containing the features/settings of the graph. However, there may be two solutions, the first of which can entirely be done in core R and the second of which involves rendering the base graphic to a grid graphic. Which solution is ultimately chosen depends on whether or not we want a uniform way of testing and comparing plots.
Possible solution 1: Comparing base graphics with recordPlot()
If a base graphic is open/active in R, then the function recordPlot() can be used to create an object containing the display list. Technically, this is not the same as a graphical object because the display list contains the calls necessary to render the graph. However, for the purpose of comparing graphs, display lists will do because the display list of a generated graph can simply be compared to the display list of an expected graph using functions like all.equal() or identical().
For instance, if we make a simple scatter plot of the first ten integers and their squares, then its display list (called display_list) can be made as follows:
The display list itself is not so informative (partial output):
display_list
List of 2
$ :Dotted pair list of 8
..$ :Dotted pair list of 2
.. ..$ :function (.NAME, ..., PACKAGE)
.. ..$ :Dotted pair list of 1
.. .. ..$ :List of 4
.. .. .. ..$ name : chr "C_plot_new"
...
However, the display lists of two separate plots can be compared with each other using e.g. all.equal():
The only issue with recordPlot() is that it can only be used with an active plot. This is of course never a problem in an interactive session but it can be a problem in an "offline" session. If the R Judge has a way of keeping track of active plots, then this can be implemented.
Possible solution 2: converting base graphics to grid graphics using the gridGraphics package
Base graphics can also be converted to grid graphics using the gridGraphics package. Since a grid graphic alway has an associated grob, this means that the grobs corresponding to two base graphics can be compared with each other. The gridGraphics package has the following functions for this purpose:
grid.echo(): render the current plot or display list as a grid graphic, thereby creating a corresponding grob
echoGrob() create a grob out of the current plot or display list, to be stored in an object
plotdiff(): compare two base graphics, using grid.echo() under the hood
...
The exact details on the arguments of these functions can be found on the help pages of the functions. The gridGraphics package is aso briefly described in Chapter 12 of Murrell, Paul (2019) R Graphics. Third Edition. A simple illustration of creating a grob based on the active plot is:
The advantage of working with the gridGraphics package is that all plots are converted to grobs, possibly allowing for a uniform way of dealing with base graphics, lattice graphics and ggplot2 graphics. The availability of the plotdiff() function could also mean that much of the work has already been done. The solution could then be to modify the testGGPlot() function so it can also handle the grobs of these other graphics.
However, that depends on which features of the grob the testGGPlot() function actually looks at: is it the whole grob or are they particular features in it which are important for the ggplot2 package? If that it settled, then it can be decided which solution is most efficient for the R Judge in order to be able to test for all important graphics in R.
The text was updated successfully, but these errors were encountered:
The function
testGGPlot()
tests whether a (student) generated ggplot2 plot is equal to an expected one, but many graphics in R are made with either the package lattice or the (core) package graphics. That means that some sort of support for these graphics needs to be provided, especially since visualization has become so important nowadays.Support for lattice graphics
A test function for a lattice plot could be perhaps be a straightforward generalization of
testGGPlot()
because lattice graphics make use of the grid system, just as ggplot2 does. That means that lattice makes a graphical object, orgrob
, that contains all the features/settings of the plot in the same way as ggplot2 does. Now, I have personally not yet had the time to find out all the details of thetestGGPlot()
function, but if it compares the generatedgrob
with the expectedgrob
, then the same thing could be done for lattice graphics: create a test function which compares the generatedgrob
with the expected one. See Chapter 6 en Chapter 7 in Murrell, Paul (2019) R Graphics. Third Edition for more information on graphical objects in the grid system.Support for base graphics
For "base" graphics made with the graphics package, things are not so easy since no graphical object is made containing the features/settings of the graph. However, there may be two solutions, the first of which can entirely be done in core R and the second of which involves rendering the base graphic to a grid graphic. Which solution is ultimately chosen depends on whether or not we want a uniform way of testing and comparing plots.
Possible solution 1: Comparing base graphics with
recordPlot()
If a base graphic is open/active in R, then the function
recordPlot()
can be used to create an object containing the display list. Technically, this is not the same as a graphical object because the display list contains the calls necessary to render the graph. However, for the purpose of comparing graphs, display lists will do because the display list of a generated graph can simply be compared to the display list of an expected graph using functions likeall.equal()
oridentical()
.For instance, if we make a simple scatter plot of the first ten integers and their squares, then its display list (called
display_list
) can be made as follows:The display list itself is not so informative (partial output):
However, the display lists of two separate plots can be compared with each other using e.g.
all.equal()
:For a plot with different features, e.g. containing the cubes of the first ten integers:
The only issue with
recordPlot()
is that it can only be used with an active plot. This is of course never a problem in an interactive session but it can be a problem in an "offline" session. If the R Judge has a way of keeping track of active plots, then this can be implemented.Possible solution 2: converting base graphics to grid graphics using the gridGraphics package
Base graphics can also be converted to grid graphics using the gridGraphics package. Since a grid graphic alway has an associated
grob
, this means that thegrob
s corresponding to two base graphics can be compared with each other. The gridGraphics package has the following functions for this purpose:grid.echo()
: render the current plot or display list as a grid graphic, thereby creating a correspondinggrob
echoGrob()
create agrob
out of the current plot or display list, to be stored in an objectplotdiff()
: compare two base graphics, usinggrid.echo()
under the hoodThe exact details on the arguments of these functions can be found on the help pages of the functions. The gridGraphics package is aso briefly described in Chapter 12 of Murrell, Paul (2019) R Graphics. Third Edition. A simple illustration of creating a
grob
based on the active plot is:An illustration of creating a
grob
based on a display list (i.e. the output ofrecordPlot()
):Creating a
grob
of a plot command can also be done, but this requires the plot command to be wrapped in a function without arguments:etc.
The advantage of working with the gridGraphics package is that all plots are converted to
grob
s, possibly allowing for a uniform way of dealing with base graphics, lattice graphics and ggplot2 graphics. The availability of theplotdiff()
function could also mean that much of the work has already been done. The solution could then be to modify thetestGGPlot()
function so it can also handle thegrob
s of these other graphics.However, that depends on which features of the
grob
thetestGGPlot()
function actually looks at: is it the wholegrob
or are they particular features in it which are important for the ggplot2 package? If that it settled, then it can be decided which solution is most efficient for the R Judge in order to be able to test for all important graphics in R.The text was updated successfully, but these errors were encountered: