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 │ │ │ │
├───────────┼────────────────┼───────────┼──────────────┤
│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 │
└───────────┴────────────────┴───────────┴──────────────┘
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 │ │ │ │
├───────────┼────────────────┼───────────┼──────────────┤
│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 │
└───────────┴────────────────┴───────────┴──────────────┘
activity ← ↑↑w1 w2
┌───────────┬────────────────┬───────────┬──────────────┐
│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 │
└───────────┴────────────────┴───────────┴──────────────┘
┌───────────┬────────────────┬───────────┬──────────────┐
│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 │
└───────────┴────────────────┴───────────┴──────────────┘
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 │ │ │ │
├───────────┼────────────────┼───────────┼──────────────┤
│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 │
└───────────┴────────────────┴───────────┴──────────────┘
⍝ Data from first day of both weeks
activity[;3;]
12 8 15 6
15 11 17 8
activity[;;1]
┌──────┬───────────┬──┬──┬──┬──┬──┬──┬──┐
│Week 1│RedScanLine│12│10│14│11│9 │13│10│
├──────┼───────────┼──┼──┼──┼──┼──┼──┼──┤
│Week 2│RedScanLine│15│12│11│14│10│13│12│
└──────┴───────────┴──┴──┴──┴──┴──┴──┴──┘
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│ │ │ │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│
├──────┼──────┼──────┼──────┼───────────┼────────────────┼───────────┼──────────────┼──┼──┼──┼─┼──┼─┼──┼─┼──┼──┼──┼─┼──┼─┼──┼─┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼─┤
│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│
└──────┴──────┴──────┴──────┴───────────┴────────────────┴───────────┴──────────────┴──┴──┴──┴─┴──┴─┴──┴─┴──┴──┴──┴─┴──┴─┴──┴─┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴─┘
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 │ │ │ │
├───────────┼────────────────┼───────────┼──────────────┤
│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 │
└───────────┴────────────────┴───────────┴──────────────┘
┌───────────┬────────────────┬───────────┬──────────────┐
│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 │
└───────────┴────────────────┴───────────┴──────────────┘
⍝ 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 │
└────────────────┴────────────────┘
┌────────────────┬────────────────┐
│ │ │
├────────────────┼────────────────┤
│frequencySniffer│frequencySniffer│
├────────────────┼────────────────┤
│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 │││ │ │││ │ │││ │ ││
│├───────────┼───────────┤│├────────────────┼────────────────┤│├───────────┼───────────┤│├──────────────┼──────────────┤│
││RedScanLine│RedScanLine│││frequencySniffer│frequencySniffer│││dataMoshpit│dataMoshpit│││Radiovangelist│Radiovangelist││
│├───────────┼───────────┤│├────────────────┼────────────────┤│├───────────┼───────────┤│├──────────────┼──────────────┤│
││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 2⍉PEOPLE
⍣≢^
⍤⍬∧
⍨⌿^
⍥⍀∧
⍝ head to toe, first couple to second couple, first partner to second partner
2 1 3⍉PEOPLE
⍣⍤
⍨⍥
≢⍬
⌿⍀
^∧
^∧
⍝ first partner to second partner, head to toe, first couple to second couple
3 2 1⍉PEOPLE
⍣⍨
≢⌿
^^
⍤⍥
⍬⍀
∧∧
⍝ 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: |: