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