Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • check if an object is a colvec/rowvec/matrix

    I wrote helper functions:

    Code:
    function is_colvec(z) return(anyof(("colvector","scalar"),orgtype(z)))
    function is_rowvec(z) return(anyof(("rowvector","scalar"),orgtype(z)))
    function is_matrix(z) return(anyof(("matrix","colvector","rowvector","scalar"),orgtype(z)))
    I'm wondering if I needed to. Are there built-in functions that indicate 0/1 whether an object `x` is a colvec/rowvec/matrix? I know that these types are nested (so a rowvector is a special type of matrix, etc.), but can't see anywhere where that is formalized in a way that I can use directly.

    That's my main question, but I have a couple more following the code below.

    Here's my application: I wanted union and intersection functions that work on either a pair of row vectors or column vectors:**

    Code:
    function get_union(x,y){
        
        is_col = is_colvec(x) & is_colvec(y)
        is_row = is_rowvec(x) & is_rowvec(y)
        
        if (!(is_col|is_row)) return("conformability problem")
        
        res = is_col ? sort(uniqrows( (x\y) ),1) : sort(uniqrows( (x,y)' ),1)'
            
        return(res)
    }
    
    function get_intersection(x,y){
    
        xy   = get_union(x,y)
        x    = is_colvec(x) ? sort(uniqrows(x),1) : sort(uniqrows(x'),1)'
        y    = is_colvec(y) ? sort(uniqrows(y),1) : sort(uniqrows(y'),1)'
        
        n_xy = length(xy)
        in   = is_colvec(xy) ? J(n_xy,1,0) : J(1,n_xy,0)
    
        xi   = 1
        yi   = 1
        i      = 1
        
        while (i <= n_xy & xi <= length(x) & yi <= length(y)){
            v  = xy[i]
            
            dx = x[xi]==v
            dy = y[yi]==v
            
            if (dx) xi++
            if (dy) yi++
            in[i] = dx*dy
            i++
        }
    
        return(select(xy,in))
    }
    
    // example
    
    x = 3,3,1
    y = 2,4,3
    
    get_intersection(x,y)
    Two more minor questions if you've come this far:
    • When I run my example, the objects x and y outside of the function are modified, which is unexpected. I thought Mata functions didn't have side effects like this...?
    • Is there a standard way to make aliases for a Mata function? I'm inclined to do something like
    Code:
    function get_intersect(x,y) get_intersection(x,y)
    function intersect(x,y) get_intersection(x,y)
    so that I can afford to forget what I named my function.

    ** Working on more than a pair of vectors at once would be better, but I'll attempt that some other time. By the way, I'm using get_* instead of the vanilla names for these operations because "union" and "intersection" are reserved words/function names (since they may be implemented by StataCorp in the future, which might break code I'm writing now). And the reason why I'm making these functions in the first place is that I'm sick of taking my Mata objects to Stata and doing merges (which is the best, albeit clumsy, workaround I had up until this point). It would be really nice if we eventually got a "vectorized" version of inlist in Mata, so I could write intersect as

    Code:
    u = union(x,y)
    return(select(u,inlist(x,u):&inlist(y,u)))
    (...or something along those lines.) A related thread: http://www.stata.com/statalist/archi.../msg00811.html
    Last edited by Frank Erickson; 05 Jun 2015, 12:42.

  • #2
    Regarding your first minor question, in Mata arguments are passed by reference and not by value (Unlike in C). It means that any operation on the arguments of the function within the function will alterate these arguments.


    Comment


    • #3
      As far as I can see in the manual there are no such functions (not even in the undocumented list). But your functions do a pretty good job :-)

      Comment


      • #4
        Cool, thanks for the info, Christophe. In that case, I'll create new objects instead of overwriting my input (which may have been a confusing way to code it, anyways).

        EDIT: By the way, where can one see the list of undocumented functions?

        Comment


        • #5
          Just type help undocumented and you will get the list of undocumented commands. There is a section dedicated to Mata.

          Aside: One function I have found (very) useful is panelsum(). It's fast. don't know why it is still undocumented and not part of the official documentation though.

          Comment


          • #6
            Thanks again! panelsum does sound useful. I use regexm and timer_* all the time, so I'm surprised to see them on the list.

            Comment

            Working...
            X