v←10 20 30 40 50
v.[[0 ¯1]]
v₋₁10 50
50
BPL has three ways to select. I⌷A takes selectors for leading axes and gives every combination of them. A.[I J] pairs its arrays of positions item by item, as NumPy’s advanced indexing does. P⊃A follows a path into nested arrays. Each section below shows an everyday task and the form that does it. Axis keys covers selecting by key.
Positions count from 0. A negative position counts from the end, as in Python:
A position past the end of an axis is an INDEX error. : selects one whole axis. ∞ selects all remaining axes here. Reverse, ⌽, reverses the last axis:
¯∞ inserts an unnamed, unkeyed axis of length one without consuming an input axis. It works with both forms of indexing, as Python’s None does:
⌷ selects every combination of its positions. Here are rows 1 and 2 with columns 0 and 3:
.[] pairs its arrays instead. The same two arrays read m at row 1, column 0 and at row 2, column 3:
Named positions build the block for you. Arrays with different axis names don’t pair. Each keeps its own axis, as in xarray’s broadcasting by dimension name:
Pairing picks one item from each row. k gives a column for each row of m, as NumPy’s m[np.arange(3), k] does:
A classifier’s loss reads the probability of each sample’s true class. Each column of P holds one sample’s probabilities for three classes. L gives each sample’s true class. The loss is the mean negative log of those probabilities:
0.7 0.8 0.5 0.8
0.3740273068
With named axes, the same pick works through names. labels holds one class number for each sample, along the sample axis b. Because labels and b share that name, they pair and take Pn’s axes in order. labels gives the row and b gives the column, as in P.[L ⍳4ₓ]:
An array that appears twice pairs with itself, giving a diagonal:
⍋⍠"i" sc grades each column of sc, giving that column’s rows in sorted order. The grades carry both of sc’s axis names. As a selector, they read rows while their j axis lines up with sc’s columns. Each column of sc is read in sorted order, as NumPy’s take_along_axis does with argsort:
⍸ gives the coordinates where a condition holds. A selector of coordinates reads at each one:
Assigning through the same selector changes those items:
⊃ follows a path into nested arrays, one level for each item of the path. Item 2 of item 1:
Index also takes arrays of paths, with ¯∞ placing new axes before the paths or among the selected cells’ axes.
Adding two named indices builds a table of positions, because their names differ. Reading a vector through that table gives sliding windows:
Differences between neighbours read a vector twice, one position apart:
A neighbour’s position comes from arithmetic and can fall off the axis. At the start, e-1 is ¯1, which reads the last item:
•edge says what happens at the edge instead. 4•edge e-1 turns each position outside an axis of length 4 into NaN. A NaN position reads fill. Reading u through these positions shifts it right, with a zero at the start:
•edge "clamp" gives a function that moves each position outside the axis to the nearest end instead. "wrap", "reflect" and "symmetric" give the other modes:
On an axis of length 6, here is where each mode sends the positions from ¯2 to 5:
Any selection can be an assignment target:
To write a block, use ⌷ with a space before ←. The space makes the whole run before it the target:
Modified assignment applies once for each time a position appears. Counting a histogram takes one line:
A write through a NaN position writes nothing. Passing bin numbers through •edge first drops the values that fall outside the bins, here 7 and ¯1:
A write is dropped wherever the same read gives fill. 5↑abc reads two fills past the end of abc. Writing through it changes only the three items that exist:
First of an empty string reads a fill. Under can therefore change the first letter of each word, empty words included, with no special case. 1•c converts to uppercase:
f@g applies f to the selection that g makes, then writes the result back:
After a function, .[I] selects from its result. Under can use ⊢.[I] as its selector, with no dfn:
⊢.name reads a field in the same way, as {⍵.name} does:
A named index on its own reads the axis with its name, wherever it’s written. sales.[mo cy] reads months with mo and cities with cy. The result is sales itself:
$t
•index gives an index along a fresh name. Two fresh indices build a grid. Subtracting one reading of q from another gives the difference between every pair of items: