# Indexing


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

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](keyed.ipynb) covers selecting by key.

## Positions

Positions count from 0. A negative position counts from the end, as in
Python:

``` bpl
v←10 20 30 40 50
v.[[0 ¯1]]
v₋₁
```

    10 50

    50

A position past the end of an axis is an `INDEX` error. `:` selects one
whole axis. `∞` selects all remaining axes here.
[Reverse](glyphs/circle-stile.qmd), `⌽`, reverses the last axis:

``` bpl
m←[0 1 2 3⋄4 5 6 7⋄8 9 10 11]
⌽m
```

     3  2 1 0
     7  6 5 4
    11 10 9 8

`¯∞` 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:

``` bpl
⍴[¯∞ ∞]⌷m
⍴m.[: ¯∞ :]
```

    [1 3 4]ₓ

    [3 1 4]ₓ

## Blocks of rows and columns

`⌷` selects every combination of its positions. Here are rows 1 and 2
with columns 0 and 3:

``` bpl
[1 2;0 3]⌷m
```

    4  7
    8 11

`.[]` pairs its arrays instead. The same two arrays read `m` at row 1,
column 0 and at row 2, column 3:

``` bpl
m.[[1 2] [0 3]]
```

    4 11

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:

``` bpl
x←["i":5 "j":5]⍴⍳25
r←1ₓ+⍳["i":3ₓ] ⋄ c←2ₓ+⍳["j":2ₓ]
x.[r c]
```

     7  8
    12 13
    17 18

## One item from each row or column

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:

``` bpl
k←[2 0 3]ₓ
m.[⍳3ₓ k]
```

    2 4 11

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:

``` bpl
P←[0.7 0.1 0.2 0.1⋄0.2 0.8 0.3 0.1⋄0.1 0.1 0.5 0.8]
L←[0 1 2 2]ₓ
P.[L ⍳4ₓ]
- +/÷≢ ⍟P.[L ⍳4ₓ]
```

    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ₓ]`:

``` bpl
Pn←["c":3 "b":4]⍴P
labels←["b":4]⍴L ⋄ b←⍳["b":4]
Pn.[labels b]
```

    ["b":4]⍴[0.7 0.8 0.5 0.8]

An array that appears twice pairs with itself, giving a diagonal:

``` bpl
i←⍳3ₓ ⋄ m.[i i]
```

    0 5 10

## Sorting each column

`⍋⍠"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`:

``` bpl
sc←["i":3 "j":4]⍴[3 1 4 1⋄5 9 2 6⋄5 3 5 8]
gr←⍋⍠"i" sc
gr
sc.[gr]
```

    [0 0 1 0
     1 2 0 1
     2 1 2 2]ₓ

    3 1 2 1
    5 3 4 6
    5 9 5 8

## Coordinates

`⍸` gives the coordinates where a condition holds. A selector of
coordinates reads at each one:

``` bpl
m.[⍸m>8]
```

    9 10 11

Assigning through the same selector changes those items:

``` bpl
z←m ⋄ z.[⍸z>8]←0 ⋄ z
```

    0 1 2 3
    4 5 6 7
    8 0 0 0

## Paths

`⊃` follows a path into nested arrays, one level for each item of the
path. Item 2 of item 1:

``` bpl
n←[1 2;3 4 5]
[1 2]⊃n
```

    5

[Index](glyphs/squad.qmd) also takes arrays of paths, with `¯∞` placing
new axes before the paths or among the selected cells’ axes.

## Windows and neighbours

Adding two named indices builds a table of positions, because their
names differ. Reading a vector through that table gives sliding windows:

``` bpl
w←10 20 30 40 50 ⋄ s←⍳["s":3] ⋄ t←⍳["t":3]
s+t
w.[s+t]
```

    0 1 2
    1 2 3
    2 3 4

    10 20 30
    20 30 40
    30 40 50

Differences between neighbours read a vector twice, one position apart:

``` bpl
y←10 20 40 70 ⋄ p←⍳["p":3]
y.[p+1]-y.[p]
```

    ["p":3]⍴[10 20 30]

## Edges

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:

``` bpl
u←10 20 30 40 ⋄ e←⍳4ₓ
u.[e-1ₓ]
```

    40 10 20 30

[`•edge`](system/edge.qmd) 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:

``` bpl
4•edge e-1
u.[(4•edge e-1)]
```

    $n 0 1 2

    0 10 20 30

`•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:

``` bpl
clamp←•edge "clamp"
u.[(4 clamp e-1)]
```

    10 10 20 30

On an axis of length 6, here is where each mode sends the positions from
¯2 to 5:

``` bpl
[wrap reflect symmetric]←•edge "wrap" "reflect" "symmetric"
pos←¯2ₓ+⍳8ₓ
6 clamp pos
6 wrap pos
6 reflect pos
6 symmetric pos
```

    [0 0 0 1 2 3 4 5]ₓ

    [4 5 0 1 2 3 4 5]ₓ

    [2 1 0 1 2 3 4 5]ₓ

    [1 0 0 1 2 3 4 5]ₓ

## Changing a selection

Any selection can be an assignment target:

``` bpl
a←10 20 30 40 50 ⋄ a.[[1 3]]←0 ⋄ a
```

    10 0 30 0 50

To write a block, use `⌷` with a space before `←`. The space makes the
whole run before it the target:

``` bpl
bk←3 6⍴0 ⋄ [0 2;1 4]⌷bk +←10 ⋄ bk
```

    0 10 0 0 10 0
    0  0 0 0  0 0
    0 10 0 0 10 0

Modified assignment applies once for each time a position appears.
Counting a histogram takes one line:

``` bpl
h←5⍴0 ⋄ h.[[1 3 1 1]]+←1 ⋄ h
```

    0 3 0 1 0

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:

``` bpl
g←5⍴0 ⋄ d←0.5 1.5 1.7 4.2 7 ¯1
g.[(5•edge ⌊d)]+←1 ⋄ g
```

    1 2 0 0 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:

``` bpl
abc←1 2 3 ⋄ 5↑abc ←10 20 30 40 50 ⋄ abc
```

    10 20 30

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:

``` bpl
1•c@↑¨ "hello" "" "world"
```

    "Hello" "" "World"

## Under

`f@g` applies `f` to the selection that `g` makes, then writes the
result back:

``` bpl
{⍵×10}@[1 3] u
```

    10 200 30 400

After a function, `.[I]` selects from its result. Under can use `⊢.[I]`
as its selector, with no dfn:

``` bpl
{⍵×10}@ ⊢.[[1 3]] u
```

    10 200 30 400

`⊢.name` reads a field in the same way, as `{⍵.name}` does:

``` bpl
orders←[["price":10 "qty":2] ["price":5 "qty":1]]
⊢.price¨ orders
```

    10 5

## Named and fresh indices

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:

``` bpl
sales←["city":"NY" "LA";"month":"Jan" "Feb" "Mar"]:[10 20 30⋄40 50 60]
cy←⍳⍠"city" sales ⋄ mo←⍳⍠"month" sales
sales≡sales.[mo cy]
```

    $t

[`•index`](system/index.qmd) 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:

``` bpl
q←10 20 40 ⋄ [ri ci]←•index 3 3
q.[ri]-q.[ci]
```

     0 ¯10 ¯30
    10   0 ¯20
    30  20   0
