ann@neuro.usc.edu (Ann Simpson Chapin) (06/21/91)
Does anyone know how to grade down the columns of an array (rank 2) so that each column of the array is graded down as if it is a separate vector? I do not want to have to create an interative function, and I also do not want to have to create separate vectors from each column, grade down each vector, and then reconcatenate the vectors into the original array. I have received several suggestions from various sources about creating nested indicies into the array to solve the problem, but everyone I know that has tried to solve this problem in a noniterative fashion has not been able to. If you can do this, please include the steps in your response. I am using APL Plus II on a 386 with plenty on memory and a math coprocessor..... Thanks, Ann
ljdickey@watmath.waterloo.edu (L.J.Dickey) (06/21/91)
In article <33789@usc.edu> ann@neuro.usc.edu (Ann Simpson Chapin) writes: >Does anyone know how to grade down the columns of an array (rank 2) so that >each column of the array is graded down as if it is a separate vector? I have a solution to this problem. >I do not want to have to create an interative function, and I also do not >want to have to create separate vectors from each column, grade down each >vector, and then reconcatenate the vectors into the original array. Yeah, that would be a pain. >I have received several suggestions from various sources about creating >nested indicies into the array to solve the problem, but everyone I know >that has tried to solve this problem in a noniterative fashion has not >been able to. If you can do this, please include the steps in your >response. Here are the steps in my solution, straight from a session script: NB: =: '0 0$0' : 'x.' shape =. 4 5 m =. (($?~)*/) shape NB: 'Deal me a matrix.' m NB: 'What did I get?' 6 7 1 2 18 13 4 15 3 0 16 19 12 17 14 8 10 11 5 9 r =. (\:"1)&.|:m NB: 'Grade down each row under transpose.' c =. ($m)$i.}.$m NB: 'Plain column selectors.' ( <"1 r,"_2 c ){m NB: 'The desired result.' 16 19 15 17 18 13 10 12 5 14 8 7 11 3 9 6 4 1 2 0 ( <"1 r,"_2 c ) NB: 'The indices.' +---+---+---+---+---+ |2 0|2 1|1 2|2 3|0 4| +---+---+---+---+---+ |1 0|3 1|2 2|3 3|2 4| +---+---+---+---+---+ |3 0|0 1|3 2|1 3|3 4| +---+---+---+---+---+ |0 0|1 1|0 2|0 3|1 4| +---+---+---+---+---+ Comments: The thing that makes this relatively easy in J is the way the rank operator can be used to great advantage. The first place this happens is in the expression \:"1 which means grade down each row. I used this on each row of the transpose, and then transposed the result back to get "r". This was the most interesting part for me. The second most interesting part was discovering how to put the row indices and column indices together to generate the subscripts used to select from the matrix. For me, the expression ( <"1 r,"_2 c ) was enlightening. > I am using APL Plus II on a 386 with plenty on memory and a >math coprocessor..... > >Thanks, Ann I am using J, Version 3.2 on my Atari Mega ST2. Thank you, Ann, for posting such an interesting question. I have learned a little more about J and the rank operator. -- Prof L.J. Dickey, Faculty of Mathematics, U of Waterloo, Canada N2L 3G1 internet: ljdickey@watmath.UWaterloo.ca BITNET/EARN: ljdickey@watdcs obsolescent?: ljdickey@watmath.waterloo.edu UUCP: ljdickey@watmath.UUCP ..!uunet!watmath!ljdickey
rockwell@socrates.umd.edu (Raul Rockwell) (06/21/91)
Ann Simpson Chapin: Does anyone know how to grade down the columns of an array (rank 2) so that each column of the array is graded down as if it is a separate vector? I do not want to have to create an interactive function .. I am using APL Plus II on a 386 with plenty on memory and a math coprocessor..... Well, if you were using J, I'd recommend something like \:~ "1 &.|: array But since you're not, I'll try and describe a way to do this in vanilla APL. Basically, you coerce the array to a vector, sort the vector in a way which preserves the original column order, then reshape back to the original shape. First off, you'll need the array in vector form. You'll want all members of a single column adjacent to each other, so you need to transpose the array before you ravel it. I'm going to give each sentence twice -- once in psuedo-apl puns, and once in J. vec <- , (\) array vec =. , |: array Second off, you'll need to grade the array. You want the grade to preserve the original column ordering, so you need to normalize the array, and add numbers to force the proper static ordering. normalized <- /|\ /|\ array normalized =. /: /: array colHorder <- - (R vec) x (R array)[0] / i (R array)[1] col_order =. - (# vec) * (0{$array) # i. 1{$array grade <- \|/ colHorder + normalized grade =. \: col_order + normalized Finally, you need to restore the original shape of the array. Note that you need to do a transpose as well, which means that you need to reshape using transposed dimensions. (I'll just reverse the dimensions here). sorted <- (\) ( (|) R array)R vec[grade] sorted =. |: ( |. $ array)$ grade{vec voila. As an aside, I haven't tested this code yet, but the basic concept is sound. I hope you can read it. Also note that I've assumed origin 0 for the APL session -- I trust conversion to origin 1 is obvious, if that is desired. puns used here: <- assignment (\) transpose (|) rotate R rho H delta x times -- Raul <rockwell@socrates.umd.edu>
rockwell@socrates.umd.edu (Raul Rockwell) (06/23/91)
Just a couple second thoughts on the sorting method I mentioned in my last post. First, one does not need to to transpose the array before ravelling it. Since the sort will totally reorder the array, and since the key I provided results in a transposed array after sorting, the initial transpose is redundant. (Though it is probably useful conceptually). Second, the normalization technique I used wouldn't work if you wanted to maintain the relative positions of "identical" elements. I think this might be significant with floating point values, because of the effects of comparison tolerance. Also, I mistyped at least one bug into the code. So, ammended code (same puns as before): vec <- , array vec =. , array normalized <- \|/ \|/ vec normalized =. \: \: vec colHorder <- - (R vec) x (R array)R i (R array)[1] col_order =. - (# vec) * ($ array)$ i. 1{$ array grade <- \|/ colHorder + normalized grade =. \: col_order + normalized sorted <- vec [ (\) ( (|) R array ) R grade ] sorted =. vec {~ |: ( |. $ array ) $ grade (the typo in my prior post, by the way, was where I used 'array' rather than 'vec' to compute 'normalized') Finally note that my use of intermediate variables is purely stylistic -- all of these values could be computed on the fly (though there may be a significant cost associated with computing 'vec' on the fly in some dialects of APL). -- Raul <rockwell@socrates.umd.edu>
rbe@yrloc.ipsa.reuter.COM (Robert Bernecky) (06/24/91)
In article <33789@usc.edu> ann@neuro.usc.edu (Ann Simpson Chapin) writes: >Does anyone know how to grade down the columns of an array (rank 2) so that >each column of the array is graded down as if it is a separate vector? >I do not want to have to create an interative function, and I also do not >want to have to create separate vectors from each column, grade down each >vector, and then reconcatenate the vectors into the original array. >response. I am using APL Plus II on a 386 with plenty on memory and a >math coprocessor..... As pointed out by LJ DIckey, you can use function rank if using a modern dialect of APL (J or SHARP APL/PC). Otherwise, you can try this approach, which I used back in the dark ages on a card sorter, IF your data is small numbers such as student test scores, etc. Consider the array x to be numbers in the range from 0 to 100. Add 1000 to column one, 2000 to column two, etc. In SHARP APL, this would be x+rank 1 (1000 times iota negative one take rho x). Now ravel and upgrade, than take the 1000 residue. Basically, each set of numbers sorts within the x000'th column. Bob Robert Bernecky rbe@yrloc.ipsa.reuter.com bernecky@itrchq.itrc.on.ca Snake Island Research Inc (416) 368-6944 FAX: (416) 360-4694 18 Fifth Street, Ward's Island Toronto, Ontario M5J 2B9 Canada
ljdickey@watmath.waterloo.edu (L.J.Dickey) (06/24/91)
In article <1991Jun21.060649.919@watmath.waterloo.edu> I wrote: >In article <33789@usc.edu> ann@neuro.usc.edu (Ann Simpson Chapin) writes: >>Does anyone know how to grade down the columns of an array (rank 2) so that >>each column of the array is graded down as if it is a separate vector? > >I have a solution to this problem. > ... Well, I have thought a little more about this and have learned some more. Earlier, I presented this: NB: =: '0 0$0' : 'x.' shape =. 4 5 m =. (($?~)*/) shape NB: 'Deal me a matrix.' m NB: 'What did I get?' r =. (\:"1)&.|:m NB: 'Grade down each row under transpose.' c =. ($m)$i.}.$m NB: 'Plain column selectors.' ( <"1 r,"_2 c ){m NB: 'The desired result.' Here, I will show another solution that I found, a solution that is far superior, in my opinion: (\:"1 m) {"1 m This can be presented as a tacit function sbr =. {"1 ~ \:"1 sbr m and of course, as a consequence, the expression sbr &. |: m does the desired task. Finally, as was gently pointed out by two kind readers, the expression \:~ "1 m simply sorts by rows. So, \:~ "1 &. |: m sorts by columns. I suppose that when all else fails, RYFM. (*) Further comments: My original solution seems quite silly to me now, because of the complicated structure that I needed to build. I have not found a use for the indices yet. I am afraid that it will be just an amusing exercise. As before, the rank operator plays an essential role in each of the above solutions. But in these two solutions above, strong primitives are used (sort and grade down) Lee Dickey (*) Reference: ``Computer Wimp'', by John Baer. Ten Speed Press, Berkeley (1983), ISBN 0-89815-101-5, p. 204. -- Prof L.J. Dickey, Faculty of Mathematics, U of Waterloo, Canada N2L 3G1 internet: ljdickey@watmath.UWaterloo.ca BITNET/EARN: ljdickey@watdcs obsolescent?: ljdickey@watmath.waterloo.edu UUCP: ljdickey@watmath.UUCP ..!uunet!watmath!ljdickey
jaxon@sp27.csrd.uiuc.edu (Greg P. Jaxon) (06/26/91)
It seems we just went through this topic a month ago, it must be an assigned puzzle. Here is a standard APL solution, but there are far more efficient APL2-style solutions. $ Z is COLUMN_SORT A;#IO;#CT;T [1] #IO is #CT is 0 [2] T is reverse rho A [3] Z is grdn A is ,A [4] Z is A[transpose T rho Z[grup T[0]|Z]] $ Greg Jaxon P.S. I wouldn't turn this in to an APL instructor unless I could identify which primitive function is using #CT!