How do I access the n-th column of a boxed array?
Asked Answered
S

3

3

Given I have a boxed array with shape 4 3

v =. 4 3$'x1'; 'y1'; 'z1'; 'x2'; 'y2'; 'z2'; 'x3'; 'y3'; 'z3'
v
NB. +--+--+--+
NB. |x1|y1|z1|
NB. +--+--+--+
NB. |x2|y2|z2|
NB. +--+--+--+
NB. |x3|y3|z3|
NB. +--+--+--+
NB. |x1|y1|z1|
NB. +--+--+--+

Selection

I can get the second row via 1{::v

1{::v
NB. Get the second row
NB. +--+--+--+
NB. |x2|y2|z2|
NB. +--+--+--+

Projection

But how do I access the second column?

NB. Get the second column
NB. +--+
NB. |y1|
NB. +--+
NB. |y2|
NB. +--+
NB. |y3|
NB. +--+
NB. |y1|
NB. +--+
Salpinx answered 28/1, 2013 at 11:7 Comment(0)
D
6

You can also specify a Rank of { with ":

1 {"1 v
NB. +--+--+--+--+
NB. |y1|y2|y3|y4|
NB. +--+--+--+--+

This will give you the second column, minus a rank, so just an array of shape 4. To get it to shape 4 1, use Ravel Items ,.:

,.1 {"1 v
NB. +--+
NB. |y1|
NB. +--+
NB. |y2|
NB. +--+
NB. |y3|
NB. +--+
NB. |y1|
NB. +--+

Also, all this logic applies whether the matrix is boxed or not.

Dhiman answered 28/1, 2013 at 15:15 Comment(3)
To me, this seems to be the "proper" way. Just one note though: the left argument of { has a shape, so you can use (,1) {"1 v to get the column as a column.Hawkweed
@Hawkweed Good mention. It's just not very natural to have data displayed like that in a single column, but if the need is for that layout, shaping if after with $ or ,. is more explicit than during the operation with a shaped index to {. But it does the job.Dhiman
Yes, if the need is cosmetic (i.e. about display, rather than subsequent computation) subsequent reshaping seems clearer. This question sounds to me to request a result with shape (1 4) in which case including the shape in the left argument seems clearer. Experience with J teaches that we typically want to extract a column as simple list, not as "a column" (with the extra axis) but learning requires playing with both.Lysis
M
3

As the other posters observed, array access in J is weighted toward the primary (leading) axis. That is, the J language makes it easy to address the elements along the length of the array (first item, second item, third item, etc).

To access non-leading axes, the J programmer will normally adopt one of two strategies, as demonstrated by abstraktor's and MPelletier's responses respectively:

  • Change the array, so that the axis of interest actually becomes the leading axis; in your case, by converting the 2nd ("column") axis into the 1st ("row") axis, as demonstrated in abstraktor's solution using |: .

  • Or change the accessor function's perspective, so that the axis of interest looks like the leading axis from that accessor's point of view. This is exemplified by MPelletier's solution, which changes the perspective of { (which is the accessor function in your case) using rank ("). In his example, the POV of { is restricted to a single row at a time, so that now from that function's perspective the leading axis is the atoms of each row -- which, when aggregated, correspond to columns (of course).

So those are the major methods for accessing non-leading axes in J. Having said that, certain primitive functions can actually address non-leading axes directly. In fact, { is one of these, if you format its argument correctly:

   (<a:;1) { v
+--+--+--+--+
|y1|y2|y3|y1|
+--+--+--+--+

Here, we're passing a boxed left argument to { . When we do that, { understands that that box is itself to contain a list of boxes: one box per axis (item-in-the-shape-of) its right argument. Each one of those (sub-)boxes will indicate selection criteria for the corresponding axis of the right argument. Here, we've used "a:" to indicate "a"ll of the first axis, and 1 to indicate the second element of the second axis (i.e. the second column). We could also mix-and-match, e.g. "the first and last columns of the second and third rows":

   (<1 2;0 _1) { v
+--+--+
|x2|z2|
+--+--+
|x3|z3|
+--+--+

and of course this extends to N-dimensional arrays in the obvious way.

So you can use { to address non-leading axes of arrays directly. Certain other primitives share this feature, though of course they still perform their defined function on the addressed axes (so if you just want to select data, use { ).

Let's say you wanted to cut (partition) an array into columns, instead of the more usual rows. Then you can use ;. (cut) , but with a boxed left-hand argument in place of the usual open LHA:

   ('';1) <;.1 v
+----+----+----+
|+--+|+--+|+--+|
||x1|||y1|||z1||
|+--+|+--+|+--+|
||x2|||y2|||z2||
|+--+|+--+|+--+|
||x3|||y3|||z3||
|+--+|+--+|+--+|
||x1|||y1|||z1||
|+--+|+--+|+--+|
+----+----+----+

In fact, we can use this method to address more than one axis simultaneously; for example, we could group the array into pairs of rows divided at every column (i.e. into 2x1 subarrays):

   (1 0 1 0;1) <;.1 v
+----+----+----+
|+--+|+--+|+--+|
||x1|||y1|||z1||
|+--+|+--+|+--+|
||x2|||y2|||z2||
|+--+|+--+|+--+|
+----+----+----+
|+--+|+--+|+--+|
||x3|||y3|||z3||
|+--+|+--+|+--+|
||x1|||y1|||z1||
|+--+|+--+|+--+|
+----+----+----+

Or, let's say instead of selecting columns, you wanted to lop some off. Then you could use }. (drop) with a vector LHA instead of the usual scalar:

   0 1 }. v  NB. Keep all the rows but drop the first column
+--+--+
|y1|z1|
+--+--+
|y2|z2|
+--+--+
|y3|z3|
+--+--+
|y1|z1|
+--+--+


   2 _1 }. v  NB. drop the first two rows and the last column
+--+--+
|x3|y3|
+--+--+
|x1|y1|
+--+--+

Similarly for {. (take):

   _ 1 {. v   NB. Take all the rows (_=∞) but only 1 column (the first)
+--+
|x1|
+--+
|x2|
+--+
|x3|
+--+
|x1|
+--+

Similarly, a vector LHA to |. (rotate) allows us to rotate any dimension (or dimensions) of an an array back-and-forth: _2 |. v would rotate the rows of v two places, whereas 0 1 |. v would rotate the columns one place (backwards), and _2 1 |. v would do both (so the upper-left corner would be "y3").

A vector LHA also permits transpose to address any collection of axes, and move them all to the back of the array (i.e. transpose them) at once:

   $ 1 2 |: i. 11 22 33 44  NB.  Transpose the middle dimensions to the end
11 44 22 33
   $ 1 2 0 3 |: i. 11 22 33 44  NB. Mix up all dimensions
22 33 11 44

etc.

In summary, the J language is designed to make talking about the "major axis" (i.e. the first) easy, because in practice this is the most common use case. To talk about minor axes, usually you'll either physically flip the array around (using |:) to bring the axis of interest to the fore, or you'll modify your function's perspective (using ") to have an equivalent effect, from that function's point of view.

In addition, for when it's desired, J provides certain built-in tools to address non-leading axes directly, as detailed above.

Note: To keep the examples simple, the preceding discussion used the phrase "axis of interest", in the singular. But given J's array-oriented nature, it would be more precise to use the phrase "axEs of interest" (plural). In this sense, substitution of the plural for singular may be made to the both the prose and examples given without loss of generality (in fact, gaining it: the language encourages thinking in arrays, i.e. in terms of multiple dimensions simultaneously).

Mckale answered 8/7, 2013 at 20:13 Comment(0)
S
2

Projection is a selection on the transposed matrix

  1. Use the |: to transpose
  2. Select the second row (former column) with 1{::
  3. Reshape the result with 4 1$ again to be a vertical one

All in all

4 1$1{::|:v
NB. Get the second column
NB. +--+
NB. |y1|
NB. +--+
NB. |y2|
NB. +--+
NB. |y3|
NB. +--+
NB. |y1|
NB. +--+
Salpinx answered 28/1, 2013 at 11:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.