# Indexing AxisArrays by integer values (which don't start at 1...)

**URL:** <https://discourse.julialang.org/t/indexing-axisarrays-by-integer-values-which-dont-start-at-1/33749>\
**Category:** General Usage\
**Tags:** question\
**Created:** [January 24, 2020, 2:43pm UTC](https://discourse.julialang.org/t/indexing-axisarrays-by-integer-values-which-dont-start-at-1/33749 "2020-01-24T14:43:48Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![gobs](https://avatars.discourse-cdn.com/v4/letter/g/bc8723/32.png) [@gobs](https://discourse.julialang.org/u/gobs)\
**Post date:** [January 24, 2020, 2:43pm UTC](https://discourse.julialang.org/t/indexing-axisarrays-by-integer-values-which-dont-start-at-1/33749/1 "2020-01-24T14:43:48Z")

</div>

I use Axis Arrays for my modelling, but I’ve stumbled onto an annoying problem:

```julia
using AxisArrays

Y = [2019,2020] # years
x = [1, 2]

A = AxisArray(x, Y)

A[2019]
# ERROR: BoundsError: attempt to access 2-element Array{Int64,1} at index [2019]

A[atvalue(2019)]
# 1

```

I don’t particularly want to rewrite a bunch of my code to put `atvalue` everywhere, so I was wondering if there’s a cheeky workaround, e.g. make `Y` an Array of type something similar to `Int` but not `Int`, so that I can still write stuff like `Y[2] - Y[1] == 1`.

Suggestions?

---

<div class="post-metadata">

**Author:** ![gobs](https://avatars.discourse-cdn.com/v4/letter/g/bc8723/32.png) [@gobs](https://discourse.julialang.org/u/gobs)\
**Post date:** [January 24, 2020, 2:49pm UTC](https://discourse.julialang.org/t/indexing-axisarrays-by-integer-values-which-dont-start-at-1/33749/2 "2020-01-24T14:49:04Z")

</div>

I found a (partial) solution:

```julia
using AxisArrays
using Dates
Y = Year.([2019,2020]) # years

```

This sort of gives me the behaviour I want, though I eventually need the difference between years to calculate a discount rate, which wouldn’t work without some slight modification:

```julia
(Y[2] - Y[1])^0.95
# MethodError: no method matching ^(::Year, ::Float64)
(Y[2].value - Y[1].value)^0.95
# 1.00

```

---

<div class="post-metadata">

**Author:** ![AndiMD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andimd/32/6531_2.png) [@AndiMD](https://discourse.julialang.org/u/AndiMD)\
**Post date:** [January 24, 2020, 7:19pm UTC](https://discourse.julialang.org/t/indexing-axisarrays-by-integer-values-which-dont-start-at-1/33749/3 "2020-01-24T19:19:50Z")

</div>

Just introducing a wrapper type to deal with the AxisArray API is imho not very pretty.

It is not clear to me why you need the `AxisArray` type.  
Have you considered something like `OrderedDict( Y.=>x)` from the DataStructures package, or even `OffsetArrays` if you’re just dealing with increment-by-one years?

---

<div class="post-metadata">

**Author:** ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)\
**Post date:** [January 24, 2020, 9:04pm UTC](https://discourse.julialang.org/t/indexing-axisarrays-by-integer-values-which-dont-start-at-1/33749/4 "2020-01-24T21:04:41Z")

</div>

Those are good suggestions.

One way for the package’s API to avoiding such ambiguities would be to always use `A(2019)` for lookup and `A[1]` for indexing, instead of guessing based on the type as AxisArrays does. The downside is that while `A[1] = v` goes to one `setindex!` call, `A(2019) = v` tries to define a function, so won’t work. Out of curiosity, do you need to write into the array like this in what you are doing, like `A[Year(2019)] = v`?

---

<div class="post-metadata">

**Author:** ![gobs](https://avatars.discourse-cdn.com/v4/letter/g/bc8723/32.png) [@gobs](https://discourse.julialang.org/u/gobs)\
**Post date:** [January 27, 2020, 1:52pm UTC](https://discourse.julialang.org/t/indexing-axisarrays-by-integer-values-which-dont-start-at-1/33749/5 "2020-01-27T13:52:03Z")

</div>

> Have you considered something like OrderedDict( Y.=\>x) from the DataStructures package, or even OffsetArrays if you’re just dealing with increment-by-one years?

I had actually started out with `OrderedDicts`, but I was starting to get annoyed with having to write comprehensions whenever I wanted to sum over a particular axis. I’m not particularly keen on going back to them at this point.

> One way for the package’s API to avoiding such ambiguities would be to always use A(2019) for lookup and A[1] for indexing

That would be confusing though, no? Since `()` is really for function calls, so you would start to wonder whether I had a function called `A`. I do generally just fetch indices of the `AxisArrays` though, so something along those lines would be useful.

Short of any other suggestions, I might just define some super simple types to index my `AxisArrays`. Though I have a feeling that might come back to bite me in the arse at some point…

---

<div class="post-metadata">

**Author:** ![Balinus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/balinus/32/243_2.png) [@Balinus](https://discourse.julialang.org/u/Balinus)\
**Post date:** [January 27, 2020, 4:09pm UTC](https://discourse.julialang.org/t/indexing-axisarrays-by-integer-values-which-dont-start-at-1/33749/6 "2020-01-27T16:09:07Z")

</div>

Take a look at [DimensionalData.jl](https://github.com/rafaqz/DimensionalData.jl). It’s perhaps closer to what you’re looking for?

---

<div class="post-metadata">

**Author:** ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)\
**Post date:** [January 27, 2020, 4:14pm UTC](https://discourse.julialang.org/t/indexing-axisarrays-by-integer-values-which-dont-start-at-1/33749/7 "2020-01-27T16:14:53Z")

</div>

> [@gobs](#):
>
> That would be confusing though, no?

Well, isn’t the root confusion here that `A[y]` can mean either indexing (`y ∈ eachindex(A)`) or `atvalue` lookup? You know which one you want, but the computer guesses wrong.

OffsetArrays.jl doesn’t have this problem, there is only indexing. It wouldn’t be hard to make a similar array-like type which allows non-contiguous indices, but IIRC lots of things assume that axes of AbstractArrays are UnitRanges, i.e. consecutive integers. Dictionaries don’t have this problem as they don’t try to also be AbstractArrays. Perhaps Dictionaries.jl is what you want?

```julia
d1 = Dict([2018, 2020] .=> [1, 2π])
sum(d1) # error

using Dictionaries
d2 = Dictionary([2018, 2020], [1, 2π])
sum(d2)
d2 ./ 10

```

---

<div class="post-metadata">

**Author:** ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)\
**Post date:** [January 27, 2020, 4:24pm UTC](https://discourse.julialang.org/t/indexing-axisarrays-by-integer-values-which-dont-start-at-1/33749/8 "2020-01-27T16:24:29Z")

</div>

As far as I know that package doesn’t guess, and requires you to mark lookup by `At()`:

```julia
using DimensionalData
da = DimensionalArray([1, 2π], (Dim{:year}([2018, 2020]),))
da[At(2018)] == da[1]

```

---

<div class="post-metadata">

**Author:** ![Balinus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/balinus/32/243_2.png) [@Balinus](https://discourse.julialang.org/u/Balinus)\
**Post date:** [January 27, 2020, 5:05pm UTC](https://discourse.julialang.org/t/indexing-axisarrays-by-integer-values-which-dont-start-at-1/33749/9 "2020-01-27T17:05:26Z")

</div>

ah indeed. Thanks!

---

<div class="post-metadata">

**Author:** ![gobs](https://avatars.discourse-cdn.com/v4/letter/g/bc8723/32.png) [@gobs](https://discourse.julialang.org/u/gobs)\
**Post date:** [January 28, 2020, 1:08pm UTC](https://discourse.julialang.org/t/indexing-axisarrays-by-integer-values-which-dont-start-at-1/33749/10 "2020-01-28T13:08:56Z")

</div>

Offset arrays isn’t what I want, since I would also like to be able have indices which are strings. As I said before, I moved away from `OrderedDicts` and `Dicts` in general simply because I wanted to be able to write stuff like `sum(A[:,"PV",1])` instead of `sum(A[y,"PV",1] for y=Y)`. This is of course a minor issue.

What I really want is for AxisArrays to always do `A[atvalue.(y)]`. So I could just redefine `getindex(AxisArray)` to always do this within my module?
