Bookmark and Share

Notice: On April 23, 2014, Statalist moved from an email list to a forum, based at statalist.org.


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: st: Mata equivalent for R's which() or matlabs find() functions?


From   Nick Cox <[email protected]>
To   [email protected]
Subject   Re: st: Mata equivalent for R's which() or matlabs find() functions?
Date   Thu, 3 Mar 2011 09:30:55 +0000

I worked at this some more to get better (indeed, corrected) handling
of zero or one row or column input, a mild generalisation, and a
better function name, should anyone want to borrow this (i.e. a name
less likely to clash with anybody else's). The intent of this is now
to include what Ben Jann's --mm_which()-  (-moremata- from SSC) does
for vectors, although I did not use his code or his algorithm.

// row and/or column subscripts of non-zero elements of a numeric matrix
real matrix njc_which(real matrix X)
{
real matrix sub
real scalar i, j, I, J

I = rows(X); J = cols(X)

if (I == 0 | J == 0) {
	sub = J(0,0,.)
}
else if (I == 1) {
	sub = J(1,0,.)
	for (j = 1; j <= J; j++) {
        	if (X[j]) sub = sub , j
	}
}
else if (J == 1) {
	sub = J(0,1,.)
	for (i = 1; i <= I; i++) {
		if (X[i]) sub = sub \ i
	}
}
else {
	sub = J(0,2,.)
	for (i = 1; i <= I; i++) {
		for (j = 1; j <= J; j++) {
			if (X[i,j]) sub = sub \ (i,j)
		}
	}
}

return(sub)
}

end


: x = (1..42)

: njc_which(x :== 17)
  17

: njc_which(mod(x,7) :== 0)
        1    2    3    4    5    6
    +-------------------------------+
  1 |   7   14   21   28   35   42  |
    +-------------------------------+

: njc_which(mod(x',7) :== 0)
        1
    +------+
  1 |   7  |
  2 |  14  |
  3 |  21  |
  4 |  28  |
  5 |  35  |
  6 |  42  |
    +------+

: x = J(3,1,(1..3))

: x
       1   2   3
    +-------------+
  1 |  1   2   3  |
  2 |  1   2   3  |
  3 |  1   2   3  |
    +-------------+

: njc_which(x :== 2)
       1   2
    +---------+
  1 |  1   2  |
  2 |  2   2  |
  3 |  3   2  |
    +---------+

: njc_which(J(0,0,0) == 0)


On Wed, Mar 2, 2011 at 7:20 PM, Nick Cox <[email protected]> wrote:
> This now looks like a different question, so the answer is different. That's understandable.
>
> You are, it seems, going to feed your function a matrix that is already 1s when elements are what interest you and 0s otherwise. That being so, you can loop over rows and columns and pick up the subscripts that interest you. Here's an alternative version.
>
> real matrix my_which(real matrix X)
> {
>
> real matrix sub
> real scalar i, j
> sub = J(0,2,.)
>
> for (i = 1; i <= rows(X); i++) {
>        for (j = 1; j <= cols(X); j++) {
>                if (X[i,j] == 1) sub = sub \ (i,j)
>        }
> }
>
> return(sub)
> }
>
> This is longer than yours because I add declarations. But I don't see the need to bring in -select()- at all. A nuance is that if you initialise the subscripts matrix as having 0 rows then there is nothing to throw away at the end: a little mind-boggling, but Mata understands.
>
> Nothing stops this function being used for string comparisons, as in something like
>
> : frog = "foo", "bar"
>
> : my_which(frog :== "foo")
>       1   2
>    +---------+
>  1 |  1   1  |
>    +---------+
>
> -my_which()- sees the _result_ of
>
> frog :== "foo"
>
> which is numeric. So, although the generality of -transmorphic- does no harm, it is not needed either for your design.
>
> Nick
> [email protected]
>
> Sebastian Eppner
>
> Thanks a lot for the replies. The select() function really comes close
> to what I am looking for (looking into Ben Janns mm_which() tells me
> he did exactly what Bill suggested).
>
> The only problem for me is, that this strategy can be applied to
> vectors only. Because really I am interested in the position of the
> rowmax values of a MATRIX, I wrote a function that uses loops to solve
> the issue (I write the results into a matrix that looks like the one
> the R which produces); i am a mata newby, so its probably not elegant
> at all (but working):
>
>
> transmorphic matrix which_test(transmorphic matrix I)
> {
> r = J(1,2,.)
>
> for (i=1; i<=rows(I);i++) {
>
> s = I[i,.]
>
> ir = select(1..cols(I),s)
>                for (o=1; o<=cols(ir);o++) {
>                r = r \ i,ir[.,o]
>                }
> }
> return(r[2..rows(r),.])
> }
>
> mata mosave which_test(), dir(PERSONAL) replace
> end
>
>
> Lets take a vector v = 1,3,3 \ 6,5,4
> Now you can do funny things like:
>
> which_test(v:==rowmax(v))
>
> that produces the matrix 1,2 \ 1,3 \ 2,1
> (so we have 2 maximums in row 1 and 1 in row 2)
>
> or look for the position of the matrix maximum:
> which_test(v:==max(v))
>
> which returns a vector 2,1 (maximum is in row 2, column 1)
>
> and so on...
>
> Again thx for the help. I would be interested if I just wrote smth
> that is already out there. Maybe it is a good idea to include
> something like this as  find() or which() in mata.
>
> Sebastian
>

*
*   For searches and help try:
*   http://www.stata.com/help.cgi?search
*   http://www.stata.com/support/statalist/faq
*   http://www.ats.ucla.edu/stat/stata/


© Copyright 1996–2018 StataCorp LLC   |   Terms of use   |   Privacy   |   Contact us   |   Site index