Skip to content

I knew he swapped those numbers!

This part will cover

  • Transpose
  • Reverse
  • Rotate

With data stored in higher dimensional arrays, it is often necessary to rotate, flip, and transpose the axes of these arrays in order to make sense of them. This is especially true in the case of highly structured data.

Let's look at an array tracking the number of replies a user has posted per day, for two weeks

      w1  ('Week 1') ('RedScanLine' 'frequencySniffer' 'dataMoshpit' 'Radiovangelist') (12    8   15  6) (10  7   12  9) (14  9   11  8) (11  6   14  7) (9   10  13  5) (13  8   16  10) (10 12  15  6)
      w1
┌───────────┬────────────────┬───────────┬──────────────┐
Week 1                                              
├───────────┼────────────────┼───────────┼──────────────┤
RedScanLinefrequencySnifferdataMoshpitRadiovangelist
├───────────┼────────────────┼───────────┼──────────────┤
12         8               15         6             
├───────────┼────────────────┼───────────┼──────────────┤
10         7               12         9             
├───────────┼────────────────┼───────────┼──────────────┤
14         9               11         8             
├───────────┼────────────────┼───────────┼──────────────┤
11         6               14         7             
├───────────┼────────────────┼───────────┼──────────────┤
9          10              13         5             
├───────────┼────────────────┼───────────┼──────────────┤
13         8               16         10            
├───────────┼────────────────┼───────────┼──────────────┤
10         12              15         6             
└───────────┴────────────────┴───────────┴──────────────┘

      w2  ('Week 2') ('RedScanLine' 'frequencySniffer' 'dataMoshpit' 'Radiovangelist') (15    11  17  8) (12  9   14  7) (11  10  13  5) (14  8   12  9) (10  7   16  11) (13 12  15  6) (12  11  14  8)
      w2
┌───────────┬────────────────┬───────────┬──────────────┐
Week 2                                              
├───────────┼────────────────┼───────────┼──────────────┤
RedScanLinefrequencySnifferdataMoshpitRadiovangelist
├───────────┼────────────────┼───────────┼──────────────┤
15         11              17         8             
├───────────┼────────────────┼───────────┼──────────────┤
12         9               14         7             
├───────────┼────────────────┼───────────┼──────────────┤
11         10              13         5             
├───────────┼────────────────┼───────────┼──────────────┤
14         8               12         9             
├───────────┼────────────────┼───────────┼──────────────┤
10         7               16         11            
├───────────┼────────────────┼───────────┼──────────────┤
13         12              15         6             
├───────────┼────────────────┼───────────┼──────────────┤
12         11              14         8             
└───────────┴────────────────┴───────────┴──────────────┘

      activity  ↑↑w1 w2
┌───────────┬────────────────┬───────────┬──────────────┐
Week 1                                              
├───────────┼────────────────┼───────────┼──────────────┤
RedScanLinefrequencySnifferdataMoshpitRadiovangelist
├───────────┼────────────────┼───────────┼──────────────┤
12         8               15         6             
├───────────┼────────────────┼───────────┼──────────────┤
10         7               12         9             
├───────────┼────────────────┼───────────┼──────────────┤
14         9               11         8             
├───────────┼────────────────┼───────────┼──────────────┤
11         6               14         7             
├───────────┼────────────────┼───────────┼──────────────┤
9          10              13         5             
├───────────┼────────────────┼───────────┼──────────────┤
13         8               16         10            
├───────────┼────────────────┼───────────┼──────────────┤
10         12              15         6             
└───────────┴────────────────┴───────────┴──────────────┘
┌───────────┬────────────────┬───────────┬──────────────┐
Week 2                                              
├───────────┼────────────────┼───────────┼──────────────┤
RedScanLinefrequencySnifferdataMoshpitRadiovangelist
├───────────┼────────────────┼───────────┼──────────────┤
15         11              17         8             
├───────────┼────────────────┼───────────┼──────────────┤
12         9               14         7             
├───────────┼────────────────┼───────────┼──────────────┤
11         10              13         5             
├───────────┼────────────────┼───────────┼──────────────┤
14         8               12         9             
├───────────┼────────────────┼───────────┼──────────────┤
10         7               16         11            
├───────────┼────────────────┼───────────┼──────────────┤
13         12              15         6             
├───────────┼────────────────┼───────────┼──────────────┤
12         11              14         8             
└───────────┴────────────────┴───────────┴──────────────┘

The array above is structures along three axes, the first being the week, the second being the day of the week, and the third is the user. Note that there are also several non-data entries that are used to make the tables easier to read.

      ⍝ Two weeks, 7 days, 4 users (Note that there are two rows which are used for labels)
      activity
2 9 4
      activity[1;;]
┌───────────┬────────────────┬───────────┬──────────────┐
Week 1                                              
├───────────┼────────────────┼───────────┼──────────────┤
RedScanLinefrequencySnifferdataMoshpitRadiovangelist
├───────────┼────────────────┼───────────┼──────────────┤
12         8               15         6             
├───────────┼────────────────┼───────────┼──────────────┤
10         7               12         9             
├───────────┼────────────────┼───────────┼──────────────┤
14         9               11         8             
├───────────┼────────────────┼───────────┼──────────────┤
11         6               14         7             
├───────────┼────────────────┼───────────┼──────────────┤
9          10              13         5             
├───────────┼────────────────┼───────────┼──────────────┤
13         8               16         10            
├───────────┼────────────────┼───────────┼──────────────┤
10         12              15         6             
└───────────┴────────────────┴───────────┴──────────────┘
      ⍝ Data from first day of both weeks
      activity[;3;]
12  8 15 6
15 11 17 8
      activity[;;1]
┌──────┬───────────┬──┬──┬──┬──┬──┬──┬──┐
Week 1RedScanLine121014119 1310
├──────┼───────────┼──┼──┼──┼──┼──┼──┼──┤
Week 2RedScanLine15121114101312
└──────┴───────────┴──┴──┴──┴──┴──┴──┴──┘

To get the total list of replies for each user, we need to enlist along the day and week axis to be left with a matrix of replies per user per day. Unfortunately, the 2-cells of this array are not the matrix of all replies for a single user, but the matrix of all replies for a single week, as can be seen above, or by looking at how the axes are arranged as Week × (Days × User). If we used the rank ⍤ operator, instead of getting a 7 row matrix of daily replies for each user, we'd obtain a 2 row matrix of replies per week.

      (,2)activity
┌──────┬──────┬──────┬──────┬───────────┬────────────────┬───────────┬──────────────┬──┬──┬──┬─┬──┬─┬──┬─┬──┬──┬──┬─┬──┬─┬──┬─┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬─┐
Week 1                  RedScanLinefrequencySnifferdataMoshpitRadiovangelist128 156107129149 1181161479 10135 138 16101012156
├──────┼──────┼──────┼──────┼───────────┼────────────────┼───────────┼──────────────┼──┼──┼──┼─┼──┼─┼──┼─┼──┼──┼──┼─┼──┼─┼──┼─┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼─┤
Week 2                  RedScanLinefrequencySnifferdataMoshpitRadiovangelist15111781291471110135148129107 16111312156 1211148
└──────┴──────┴──────┴──────┴───────────┴────────────────┴───────────┴──────────────┴──┴──┴──┴─┴──┴─┴──┴─┴──┴──┴──┴─┴──┴─┴──┴─┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴─┘

The way to solve this is to swap the Week and User axes to get an array of the form User x (Week x Days), this problem is easily solved by the ⍉ transpose function. The left argument to the transpose function is a list of integers starting from 1, which represents where each axes is in the resulting array. For example, 1 2 3 ⍉ activity is the same as activity, but 3 2 1⍉activity swaps the first and third axis.

      ⍝ Week × Day × User
      1 2 3  activity
┌───────────┬────────────────┬───────────┬──────────────┐
Week 1                                              
├───────────┼────────────────┼───────────┼──────────────┤
RedScanLinefrequencySnifferdataMoshpitRadiovangelist
├───────────┼────────────────┼───────────┼──────────────┤
12         8               15         6             
├───────────┼────────────────┼───────────┼──────────────┤
10         7               12         9             
├───────────┼────────────────┼───────────┼──────────────┤
14         9               11         8             
├───────────┼────────────────┼───────────┼──────────────┤
11         6               14         7             
├───────────┼────────────────┼───────────┼──────────────┤
9          10              13         5             
├───────────┼────────────────┼───────────┼──────────────┤
13         8               16         10            
├───────────┼────────────────┼───────────┼──────────────┤
10         12              15         6             
└───────────┴────────────────┴───────────┴──────────────┘
┌───────────┬────────────────┬───────────┬──────────────┐
Week 2                                              
├───────────┼────────────────┼───────────┼──────────────┤
RedScanLinefrequencySnifferdataMoshpitRadiovangelist
├───────────┼────────────────┼───────────┼──────────────┤
15         11              17         8             
├───────────┼────────────────┼───────────┼──────────────┤
12         9               14         7             
├───────────┼────────────────┼───────────┼──────────────┤
11         10              13         5             
├───────────┼────────────────┼───────────┼──────────────┤
14         8               12         9             
├───────────┼────────────────┼───────────┼──────────────┤
10         7               16         11            
├───────────┼────────────────┼───────────┼──────────────┤
13         12              15         6             
├───────────┼────────────────┼───────────┼──────────────┤
12         11              14         8             
└───────────┴────────────────┴───────────┴──────────────┘
      ⍝ User × Week × Day
      3 2 1  activity
┌────────────────┬────────────────┐
Week 1          Week 2          
├────────────────┼────────────────┤
RedScanLine     RedScanLine     
├────────────────┼────────────────┤
12              15              
├────────────────┼────────────────┤
10              12              
├────────────────┼────────────────┤
14              11              
├────────────────┼────────────────┤
11              14              
├────────────────┼────────────────┤
9               10              
├────────────────┼────────────────┤
13              13              
├────────────────┼────────────────┤
10              12              
└────────────────┴────────────────┘
┌────────────────┬────────────────┐
                                
├────────────────┼────────────────┤
frequencySnifferfrequencySniffer
├────────────────┼────────────────┤
8               11              
├────────────────┼────────────────┤
7               9               
├────────────────┼────────────────┤
9               10              
├────────────────┼────────────────┤
6               8               
├────────────────┼────────────────┤
10              7               
├────────────────┼────────────────┤
8               12              
├────────────────┼────────────────┤
12              11              
└────────────────┴────────────────┘
┌────────────────┬────────────────┐
                                
├────────────────┼────────────────┤
dataMoshpit     dataMoshpit     
├────────────────┼────────────────┤
15              17              
├────────────────┼────────────────┤
12              14              
├────────────────┼────────────────┤
11              13              
├────────────────┼────────────────┤
14              12              
├────────────────┼────────────────┤
13              16              
├────────────────┼────────────────┤
16              15              
├────────────────┼────────────────┤
15              14              
└────────────────┴────────────────┘
┌────────────────┬────────────────┐
                                
├────────────────┼────────────────┤
Radiovangelist  Radiovangelist  
├────────────────┼────────────────┤
6               8               
├────────────────┼────────────────┤
9               7               
├────────────────┼────────────────┤
8               5               
├────────────────┼────────────────┤
7               9               
├────────────────┼────────────────┤
5               11              
├────────────────┼────────────────┤
10              6               
├────────────────┼────────────────┤
6               8               
└────────────────┴────────────────┘

Removing the labels

      ⍝ Check how ⍤2 acts on the above matrix
      (2)3 2 1  activity
┌─────────────────────────┬───────────────────────────────────┬─────────────────────────┬───────────────────────────────┐
│┌───────────┬───────────┐│┌────────────────┬────────────────┐│┌───────────┬───────────┐│┌──────────────┬──────────────┐│
││Week 1     Week 2     │││                                │││                      │││                            ││
│├───────────┼───────────┤│├────────────────┼────────────────┤│├───────────┼───────────┤│├──────────────┼──────────────┤│
││RedScanLineRedScanLine│││frequencySnifferfrequencySniffer│││dataMoshpitdataMoshpit│││RadiovangelistRadiovangelist││
│├───────────┼───────────┤│├────────────────┼────────────────┤│├───────────┼───────────┤│├──────────────┼──────────────┤│
││12         15         │││8               11              │││15         17         │││6             8             ││
│├───────────┼───────────┤│├────────────────┼────────────────┤│├───────────┼───────────┤│├──────────────┼──────────────┤│
││10         12         │││7               9               │││12         14         │││9             7             ││
│├───────────┼───────────┤│├────────────────┼────────────────┤│├───────────┼───────────┤│├──────────────┼──────────────┤│
││14         11         │││9               10              │││11         13         │││8             5             ││
│├───────────┼───────────┤│├────────────────┼────────────────┤│├───────────┼───────────┤│├──────────────┼──────────────┤│
││11         14         │││6               8               │││14         12         │││7             9             ││
│├───────────┼───────────┤│├────────────────┼────────────────┤│├───────────┼───────────┤│├──────────────┼──────────────┤│
││9          10         │││10              7               │││13         16         │││5             11            ││
│├───────────┼───────────┤│├────────────────┼────────────────┤│├───────────┼───────────┤│├──────────────┼──────────────┤│
││13         13         │││8               12              │││16         15         │││10            6             ││
│├───────────┼───────────┤│├────────────────┼────────────────┤│├───────────┼───────────┤│├──────────────┼──────────────┤│
││10         12         │││12              11              │││15         14         │││6             8             ││
│└───────────┴───────────┘│└────────────────┴────────────────┘│└───────────┴───────────┘│└──────────────┴──────────────┘│
└─────────────────────────┴───────────────────────────────────┴─────────────────────────┴───────────────────────────────┘
      ⍝ Use drop ↓ to remove the first two rows of every enclosed array
      2(2)3 2 1  activity
12 15
10 12
14 11
11 14
 9 10
13 13
10 12

 8 11
 7  9
 9 10
 6  8
10  7
 8 12
12 11

15 17
12 14
11 13
14 12
13 16
16 15
15 14

 6  8
 9  7
 8  5
 7  9
 5 11
10  6
 6  8
 ```

 Finally obtaining the replies per user per day

```apl
      ⍝ Ravel the above 2-cells to get the replies per day for every user
      (,2)(2(2)(3 2 1  activity))
12 15 10 12 14 11 11 14  9 10 13 13 10 12
 8 11  7  9  9 10  6  8 10  7  8 12 12 11
15 17 12 14 11 13 14 12 13 16 16 15 15 14
 6  8  9  7  8  5  7  9  5 11 10  6  6  8

      ⍝ Without the unnecessary parentheses

      (,2) 2 (2) 3 2 1  activity
12 15 10 12 14 11 11 14  9 10 13 13 10 12
 8 11  7  9  9 10  6  8 10  7  8 12 12 11
15 17 12 14 11 13 14 12 13 16 16 15 15 14
 6  8  9  7  8  5  7  9  5 11 10  6  6  8
 ```


More examples of transpose

```apl
      PEOPLE  2 3 2  '⍣⍤≢⍬^∧⍨⍥⌿⍀^∧'
      ⍝ The first axis is from first couple to second couple, the second axis is from head to toe, the third axis is from first partner to second partner
      PEOPLE
⍣⍤

^

⍨⍥
⌿⍀
^
      ⍝ Convince yourself of what was said above, remember that the last axis is the one that is filled first
      (12){ }¨PEOPLE
┌────┬────┐
1  2  
├────┼────┤
3  4  
├────┼────┤
5 ^ 6  
└────┴────┘
┌────┬────┐
7  8  
├────┼────┤
9  10 
├────┼────┤
11 ^│12 
└────┴────┘

      ⍝ Transposing the array, the axes are now

      ⍝ first couple to second couple, first partner to second partner, head to toe
      ⍝ The last axis is filled by people from head to toe, then the middle axis switches partner, and the first axis switches couple
      1 3 2PEOPLE
^


⍨⌿^
⍥⍀

      ⍝ head to toe, first couple to second couple, first partner to second partner
      2 1 3PEOPLE
⍣⍤
⍨⍥


⌿⍀

^
^

      ⍝ first partner to second partner, head to toe, first couple to second couple
      3 2 1PEOPLE
⍣⍨

^^

⍤⍥

∧∧
      ⍝ They swapped partners!

The dyadic rotate functions rotate an array by an amount specific by the left argument, around a specific axis.

       3¨'hotbloods' 'mentally' 'outbreak' 'clean' 'kyoto'
bloodshot  tallymen  breakout  ancle  tokyo

Another example:

SAD_EMOTICONS  '):' ':c' ']:' ')-:' 'D:' '>:(' ':/' ':x' ':|'

Notice that some of the sad emoticons can be turned into happy emoticons by reflecting the emoticon vertically, turning the frown upside down! The monadic ⌽ ⊖ reverse functions reflect an array along the horizontal (last) or vertical (first) axis.

        '):'
:)
        SAD_EMOTICONS
:|  :x  :/  >:(  D:  )-:  ]:  :c  ):

       ¨SAD_EMOTICONS
 :)  c:  :]  :-)  :D  (:>  /:  x:  |: