leon
December 29, 2021, 1:10am
#1
My goal is to create a function to check if my data points are valid, i.e., not an NaN and not equal to -999.

Here is the function I wrote:
`f(A) = [idx for idx in CartesianIndices(A) if @inbounds (!isnan(A[idx]) && A[idx] != -999)];`

Why does it work on vector data like N1 but not on single values like N2?

```
N1 = [3.7, 4.5];
N2 = 3.7;
```

How do I make it work for single values as well?

Thanks!

There’s no sensible way to assign a Cartesian index to a floating-point value, so Julia doesn’t implement the associated method:

```
julia> CartesianIndices(3.7)
ERROR: MethodError: no method matching CartesianIndices(::Float64)
Closest candidates are:
CartesianIndices(::CartesianIndex) at C:\Users\alexa\.julia\juliaup\julia-1.7.1+0~x64\share\julia\base\multidimensional.jl:276
CartesianIndices(::AbstractArray) at C:\Users\alexa\.julia\juliaup\julia-1.7.1+0~x64\share\julia\base\multidimensional.jl:280
CartesianIndices(::Tuple{}) at C:\Users\alexa\.julia\juliaup\julia-1.7.1+0~x64\share\julia\base\multidimensional.jl:270
...
Stacktrace:
[1] top-level scope
@ REPL[20]:1
```

You probably want to use the built-in function `findall`

instead:

```
julia> f(A) = findall(A) do Aᵢ
!isnan(Aᵢ) && Aᵢ != -999
end
f (generic function with 1 method)
julia> f([3.7, 4.5])
2-element Vector{Int64}:
1
2
julia> f(3.7)
1-element Vector{Int64}:
1
```

2 Likes

leon
December 29, 2021, 2:57am
#3
Thanks for the reply.

That’s so bad. Cartesian index is one of the fastest ways to process large amounts of data.

jishnub
December 29, 2021, 3:12am
#4
You probably want `eachindex`

here anyway instead of `CartesianIndices`

?

```
julia> f(A) = [idx for idx in eachindex(A) if @inbounds (!isnan(A[idx]) && A[idx] != -999)]
f (generic function with 1 method)
julia> N1 = [3.7, 4.5];
julia> N2 = 3.7;
julia> f(N1)
2-element Vector{Int64}:
1
2
julia> f(N2)
1-element Vector{Int64}:
1
```

Or do you require the Cartesian indices in particular?

2 Likes

leon
December 29, 2021, 1:46pm
#5
I just realize that it does not work either. Here is why:

```
YES(A) = [idx for idx in eachindex(A) if @inbounds (!isnan(A[idx]) && A[idx] != -999)];
N2 = 3.7
Ind = YES(N2)
```

`N2[Ind]`

will give me the below error:

```
ERROR: MethodError: no method matching getindex(::Float64, ::Vector{Int64})
Closest candidates are:
getindex(::Number) at /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/base/number.jl:95
getindex(::Union{AbstractChar, Number}, ::CartesianIndex{0}) at /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/base/multidimensional.jl:831
getindex(::Number, ::Integer) at /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/base/number.jl:96
...
Stacktrace:
[1] top-level scope
```

This seems to be a Julia bug to me. I mean, no indexing system should fail only because the vector is reduced down to just 1 value.

`N2[Ind...]`

to get a scalar index, or encapsulate the scalar in a container: `[N2][Ind]`

1 Like

leon
December 29, 2021, 3:14pm
#7
Do I have to write a loop so that my program will treat a scalar differently from a vector? It seems Julia wants to make something really simple really complex.

This thread is a bit odd, your scalars should probably be 1-element vectors for type stability, and then CartesianIndex would work too.

2 Likes

leon
December 29, 2021, 3:46pm
#9
Thanks! The values are generated out of an external program.

Is there a universal function to convert either a scalar, or a 1-column data, or a vector to a vector?

I tried `vec()`

, and it does not work for scalars.

`[x;]`

works for both vectors and scalars.

1 Like

Sure there is. Julia treats numbers (and characters) as 0-dimensional arrays:

```
julia> x = 3.7
3.7
julia> x[]
3.7
julia> x[CartesianIndex()]
3.7
```

so it would make sense to have something like:

```
CartesianIndices(::Union{Number,AbstractChar}) = CartesianIndex():CartesianIndex()
```

3 Likes

This gets a bit unintuitive with Julia’s multidimensional `getindex`

behavior:

```
julia> 1[]
1
julia> 1[CartesianIndex()]
1
julia> 1[1, 1]
1
julia> 1[CartesianIndex(1, 1)]
ERROR: MethodError: no method matching getindex(::Int64, ::CartesianIndex{2})
[...]
```

1 Like

That seems like a separate issue — a missing `getindex`

method (for consistency…I’m not sure how useful it is).

Julia has treated numbers as 0-dimensional arrays for years now and we long ago decided to keep it (make numbers non-iterable? · Issue #7903 · JuliaLang/julia · GitHub ), so it seems like `CartesianIndices`

should be consistent with that…

3 Likes