Wednesday 7 November 2012

how to use R introspection for obtaining a data.frame from an object

A very helpful post from Charlot Wickham from the ggplot2 mailing list about how to find out which methods to use to extract a data.frame with the data from an object.

Question:
Lecomte Jean-Baptiste
6:16 PM (20 hours ago)
to ggplot2
Dear all,

I'm trying to plot with ggplot2 the result of the function variofit of the geoR package.
It's quite simple with the basic plot :

vario100 <- variog(s100, max.dist=1)
ini.vals <- expand.grid(seq(0,1,l=5), seq(0,1,l=5))
ols <- variofit(vario100, ini=ini.vals, fix.nug=TRUE, wei="equal")
summary(ols)
wls <- variofit(vario100, ini=ini.vals, fix.nug=TRUE)
summary(wls)
plot(vario100)
lines(wls)
lines(ols, lty=2)


I can plot the points of the empirical variogram, but I can't plot the line representing the fitted variogram with ggplot2

df_vario<-data.frame(u=vario100$u,v=vario100$v)

qplot(u,v,data=df_vario)

qplot(u,v,data=df_vario)+geom_line(wls)

I have make a quick search on both ggplot2 and R-sig-Geo user list without finding any solutions.
I will appreciate any advice.
Thanks

Jean-Baptiste Lecomte
Answer:

Charlotte Wickham
11:08 PM (15 hours ago)

to Lecomteggplot2
Hi Jean-Baptiste,

There are a couple of problems with geom_line(wls).  Firstly ols and wls are special objects that ggplot knows nothing about, and secondly you are passing them in as the first argument where geom_line expects a mapping.  A general solution for this type of problem is to write a function that takes the special type of object you are interested in as an argument, and outputs a data.frame you can use ggplot to plot.

You know lines(wls) must at some point calculate enough info to draw the line you require, it's just a matter of finding out where.

This first step is too figure out what is happening in lines(ols):
> class(ols)
[1] "variomodel" "variofit"  

Tells us ols has class "variomodel", so our best bet is to look at lines.variomodel:

> ?lines.variomodel
> lines.variomodel
function (x, ...) 
{
    UseMethod("lines.variomodel")
}
<environment: namespace:geoR>

Not very helpful...looks like lines.variogram is a generic function, we need to figure out which method is being called.  

> methods("lines.variomodel")
[1] lines.variomodel.default*     lines.variomodel.grf*        
[3] lines.variomodel.krige.bayes* lines.variomodel.likGRF*     
[5] lines.variomodel.variofit*   

   Non-visible functions are asterisked

Look like lines.variomodel.variofit is our candidate:
getAnywhere("lines.variomodel.variofit")

will spit out the function, and it looks like most of it is calculating the fitted line to be used in the call to the function curve.  One way to get ggplot to plot the fitted line would be to reuse that code but instead of calling curve, outputting a data.frame that ggplot can use.  I put my attempt here: https://gist.github.com/4027851

Source that in and try:
qplot(u,v,data=df_vario) +
 geom_line(aes(x, fit), data = fitted_variofit(ols)) +
 geom_line(aes(x, fit), data = fitted_variofit(wls), linetype = "dashed")

Hope that helps,

Charlotte

No comments: