statnet / ergm.ego

Fit, Simulate and Diagnose Exponential-Family Random Graph Models to Egocentrically Sampled Network Data https://statnet.org
Other
14 stars 4 forks source link

mixingmatrix may need better error handling #44

Closed martinamorris closed 4 years ago

martinamorris commented 4 years ago

I'm getting the following errors when referencing a nonexistent object (egodata should be egodat):

> mixingmatrix(egodata$main, "race")
Error in egodata$main : object of type 'closure' is not subsettable
> ergm.ego::mixingmatrix(egodata$main, "race")
Error: 'mixingmatrix' is not an exported object from 'namespace:ergm.ego'
> ergm.ego::mixingmatrix.egodata(egodata$main, "race")
Error: 'mixingmatrix.egodata' is not an exported object from 'namespace:ergm.ego'

Is it possible to provide an informative error statement like "egodata object does not exist"?

krivit commented 4 years ago

I don't think so. The error is not being triggered by anything in mixingmatrix() or mixingmatrix.egodata() but rather in the way that R looks up objects. For example, you get the same error as follows:

> library(ergm.ego)
> egodata$main
Error in egodata$main : object of type 'closure' is not subsettable
No suitable frames for recover()

That's because there is no variable named egodata, but there is now a function (closure) named egodata, so when it can't find a variable, it tries to subset a function.

It's one of the many quirks of R that makes it more convenient for interactive data analysis but can cause unexpected behaviour like this.

martinamorris commented 4 years ago

Is it possible to put a conditional like this up top to catch the problem?

if !exists(object) {print("error message")}
krivit commented 4 years ago

That wouldn't work. The moment you try to evaluate object, it'll try to subset a closure and trigger the error. I can see one or two possible ways to handle this, but they would break other things, and we would, as far as I know, be the only package in R that does this.

Again, this is an R thing, not an ergm.ego thing. Try running

mean$x

if you don't believe me.

mbojan commented 4 years ago

I'm assuming ergm.ego version 0.5 (the CRAN version).

I'm getting the following errors when referencing a nonexistent object (egodata should be egodat):

The errors seem like you in fact did use egodata, which is a function in ergm.ego, not a non-existent egodat.

> mixingmatrix(egodata$main, "race")
Error in egodata$main : object of type 'closure' is not subsettable

above error suggests that you want to call $ operator on a function, as @krivit wrote.

> ergm.ego::mixingmatrix(egodata$main, "race")
Error: 'mixingmatrix' is not an exported object from 'namespace:ergm.ego'
> ergm.ego::mixingmatrix.egodata(egodata$main, "race")
Error: 'mixingmatrix.egodata' is not an exported object from 'namespace:ergm.ego'

above errors are because mixingmatrix() exists in the 'network' package not 'ergm.ego'. You may check changing the calls to network::mixingmatrix().

If you have a code as above but with egodat instead of egodata then everything should work, as in:

library(ergm.ego)
data("faux.mesa.high")
egodat <- as.egodata(faux.mesa.high)
network::mixingmatrix(egodat, "Sex")

To be sure, I would have to have a look how did you create egodat in the first place.

Why are you referring to the main element of egodat in your example? Objects return by egodata() do not have such an element:

> str(egodat)
List of 4
 $ egos    :'data.frame':   205 obs. of  4 variables:
  ..$ vertex.names: int [1:205] 1 2 3 4 5 6 7 8 9 10 ...
  ..$ Grade       : num [1:205] 7 7 11 8 10 10 8 11 9 9 ...
  ..$ Race        : chr [1:205] "Hisp" "Hisp" "NatAm" "Hisp" ...
  ..$ Sex         : chr [1:205] "F" "F" "M" "M" ...
 $ alters  :'data.frame':   406 obs. of  4 variables:
  ..$ vertex.names: int [1:406] 1 1 1 1 1 1 1 1 1 1 ...
  ..$ Grade       : num [1:406] 7 7 12 7 7 7 7 7 7 7 ...
  ..$ Race        : chr [1:406] "White" "NatAm" "Hisp" "NatAm" ...
  ..$ Sex         : chr [1:406] "F" "F" "F" "F" ...
 $ egoWt   : num [1:205] 1 1 1 1 1 1 1 1 1 1 ...
 $ egoIDcol: chr "vertex.names"
 - attr(*, "class")= chr "egodata"

calling mixingmatrix() on a non-existing objects gives proper informative error, it is handled by base R already:

> exists("void")
[1] FALSE
> mixingmatrix(void, "Sex")
Error in mixingmatrix(void, "Sex") : object 'void' not found
> mixingmatrix(void$main, "Sex")
Error in mixingmatrix(void$main, "Sex") : object 'void' not found
martinamorris commented 4 years ago

egodat is a list with 3 egodata elements (main, casl and inst) for a multi-layer network model we're using in EpiModel.

i (reluctantly) defer to Pavel's wisdom here...