# How to convert CartesianIndex{N} values to Int64

I’m using Clustering Pkg and function fuzzy_cmean, and try to assign the cluster number to each data.
If I use `findmax(FuzzyCMeansResult.weights, dims=2)` will give us (value, CartesianIndex(2)).
Then, I cannot find out how to use `CartesianIndex(2)` values for real data.

For example, sometimes it will give us:
CartesianIndex(1, 20)
CartesianIndex(2, 19)

CartesianIndex(601, 19)
CartesianIndex(602, 11)

I hope to use CartesianIndex(2) 2nd value for candidate cluster for each data.
So, how to convert CartesianIndex values to Int64?

1 Like

1 Like

I considered and revised description. If I need to do more, please tell it to me.
Thank you.

It would be nice to have a simple example that illustrates the problem and that doesn’t rely on any external packages. Something that can be copy pasted into the REPL.

A `CartesianIndex` represents an index into a potentially multidimensional array. So I’m not sure what converting it to an integer means. Do you mean how to convert it to a “linear index”?

``````julia> a = rand(2,2)
2×2 Array{Float64,2}:
0.57097   0.0647051
0.767868  0.531104

julia> I = LinearIndices(a)
2×2 LinearIndices{2,Tuple{Base.OneTo{Int64},Base.OneTo{Int64}}}:
1  3
2  4

julia> I[CartesianIndex(1,2)]
3
``````
5 Likes

I do not mention about “linear index”. I hope to extract index value itself.

julia> I[CartesianIndex(1,2)]
3

I hope to extract “2” from CartesianIndex(1,2).
How can I do it?

This is my output when doing the analysis.

``````julia> fuzzy_clusters = cluster_list
645×1 Array{CartesianIndex{2},2}:
CartesianIndex(1, 25)
CartesianIndex(2, 16)
CartesianIndex(3, 40)
CartesianIndex(4, 37)
CartesianIndex(5, 19)
CartesianIndex(6, 17)
CartesianIndex(7, 14)
CartesianIndex(8, 16)
CartesianIndex(9, 15)
CartesianIndex(10, 24)
CartesianIndex(11, 24)
CartesianIndex(12, 5)
CartesianIndex(13, 17)
⋮
CartesianIndex(634, 15)
CartesianIndex(635, 25)
CartesianIndex(636, 23)
CartesianIndex(637, 40)
CartesianIndex(638, 37)
CartesianIndex(639, 23)
CartesianIndex(640, 16)
CartesianIndex(641, 14)
CartesianIndex(642, 14)
CartesianIndex(643, 13)
CartesianIndex(644, 25)
CartesianIndex(645, 36)
``````

I hope extract the values “25, 16, 40, 37…,14, 13, 25, 36”.
If I get them into Array or Tuple, then I can make a new column for my DataFrame.

Just extract it with normal indexing?

``````julia> CartesianIndex(1,20)
20
``````
6 Likes

Thank you!
I got it.

`[ i for i in fuzzy_clusters ]` or `map(i->i, fuzzy_clusters)`

4 Likes

Let’s say yo have 2 dimensional array `mA = randn(10, 2)`.
I’d like array of the indices of its minimum argument along the rows:

``````vMinIdx = argmin(mA, dims = 1);
``````

In the case above `vMinIdx` is a `2-element Array{CartesianIndex{2},1}:`.
I intend to ask which row index has the value of `jj`. So I did it as following:

``````vMinIdx = map(ii -> ii, argmin(mA, dims = 1));
``````

Then I do something like `sum(mX[:, vMinIdx .== jj], dims = 2);`.

Is that the most efficient way to do so? I just copied @GunnarFarneback code as we have the same issue.

It’s unclear to me what you’re trying to do, since your code doesn’t run

``````ERROR: UndefVarError: jj not defined
``````

Also, you want the minimum argument along the rows, but on the next line you write `dims=1`, which is along the columns.

Can you clarify, at least by providing runnable code?

Is what you are looking for one of the following alternatives:

``````julia> argmin.(eachcol(mA))
2-element Array{Int64,1}:
2
7

julia> argmin.(eachrow(mA))
10-element Array{Int64,1}:
1
1
1
1
1
1
2
2
2
2
``````

?

1 Like

Well, When I say along the Rows I mean the output will be row index.
I guess I was sloppy with that. Sorry.

Basically what I’m after is something equivalent to MATLAB’s:

``````[~, vMinRowIdx] = min(mA, [], 1);
``````

So basically `vMinRowIdx` will be a vector holding the row index of the minimum value in each column of `mA`. I want to use this in a loop over `jj` which does (Again MATLAB code):

``````sum(mX(:, vMinIdx .== jj), 2);
``````

You may have a look at https://github.com/RoyiAvital/MatlabJuliaMatrixOperationsBenchmark/blob/47a52533c5533927e25c4c6e376d26490bc759f5/JuliaMatrixBenchmark0003.jl#L122.
I wanted to know I’m doing it in the most efficient way (While being readable).

It would be good if you could test your code to check that it runs. I’ve spent a couple of minutes trying to fix it so that it runs, changing `mX` to `mA`, setting values for `jj`, etc. But it just fails. Can you provide tested, runnable code?

Also, it seems like `argmin.(eachcol(mA))` answers half of your question, at least.

(Unfortunately, I cannot look more at this tonight, though.)

I linked to the code which is actually running:

``````function KMeansRunTime( matrixSize, mX )

# Assuming Samples are slong Columns (Rows are features)
numClusters     = Int64(max(round(matrixSize / 100), 1));
vClusterId      = zeros(matrixSize);
numIterations   = 10;

runTime = @elapsed begin
# http://stackoverflow.com/questions/36047516/julia-generating-unique-random-integer-array
mA          = mX[:, randperm(matrixSize)[1:numClusters]]; #<! Cluster Centroids

for ii = 1:numIterations
vClusterId[:] = map(ii -> ii, argmin(sum(mA .^ 2, dims = 1)' .- (2 .* mA' * mX), dims = 1)); #<! Is there a `~` equivalent in Julia?
for jj = 1:numClusters
mA[:, jj] = sum(mX[:, vClusterId .== jj], dims = 2) ./ sum(vClusterId .== jj);
end
end

end
``````

Assume `mX` is a matrix of `matrixSize x matrixSize`.

For instance, it is equivalent (At least my equivalent) of this MATLAB Code:

``````function [ mA, runTime ] = KMeansRunTime( matrixSize, mX )

% Assuming Samples are slong Columns (Rows are features)
% mX              = randn(matrixSize, matrixSize);
numClusters     = max(round(matrixSize / 100), 1);
vClusterId      = zeros(matrixSize, 1);
numIterations   = 10;

tic();
mA          = mX(:, randperm(matrixSize, numClusters)); %<! Cluster Centroids

for ii = 1:numIterations
[~, vClusterId(:)] = min(sum(mA .^ 2, 1).' - (2 .* mA.' * mX), [], 1);
for jj = 1:numClusters
mA(:, jj) = sum(mX(:, vClusterId == jj), 2) ./ sum(vClusterId == jj);
end

end
runTime = toc();

mA = mA(:, 1) + mA(:, end).';

end
``````

The code you linked to was a large chunk of code that was difficult to identify with your specific question. And the code snippet you included in your latest post only returns runtime, as far as I can tell, and from just reading it also appears to be missing an `end`

Including a tested minimal reproducible example, that can simply be cut and pasted will make everything much simpler. I don’t understand your resistance to this idea.

BTW, for benchmarking, you should wrap the code of interest in a function and then call it with `@benchmark`, rather than put `@elapsed` inside the function.

@DNF,

I created a file called `KMeans.jl` and this is its content:

``````using Random;

function KMeans()

matrixSize = 10
mX = randn(matrixSize, matrixSize)

numClusters = Int64(max(round(matrixSize / 100), 1))
vClusterId = zeros(matrixSize)
numIterations = 10

mA = mX[:, randperm(matrixSize)[1:numClusters]] #<! Cluster Centroids

for ii = 1:numIterations
vClusterId[:] = map(ii -> ii, argmin(sum(mA.^2, dims = 1)' .- (2 .* mA' * mX), dims = 1)) #<! Is there a `~` equivalent in Julia?
for jj = 1:numClusters
mA[:, jj] = sum(mX[:, vClusterId.==jj], dims = 2) ./ sum(vClusterId .== jj)
end
end

return mA

end
``````

I call it using `include("KMeans.jl");` and then run `mA = KMeans()`.
I’m sorry if it is not elegant MWE. I am spoiled by MATLAB simplicity to create code and scoping.

Yet I think the reference should be what I do in MATLAB above.

I have the same problem. From my own cluster-analysis code I get a vector with elements like;
“CartesianIndex(3036,1)”
I want a vector with elements only like 3036.

Would it be possible to change my code so that I get the simple integer output directly, without the need to extract from CartesianIndex output?

Yes, I’m sure you can change your code to return what you want.

That’s much easier to answer if you can provide a minimal working example of what you’re doing.

Also much easier said than done in this case.

My code that generates the output is 10 pages A4 long, so I’ll have to strip most of it to make it minimal, while making sure that it’s still working and producing the problematic output.
But I will try.

To convert CartesianIndices to linear, you can do this:

``````julia> A = rand(1:10, 4, 4)
4×4 Matrix{Int64}:
4  9  9  8
2  9  6  1
8  6  3  6
1  3  9  7

julia> results = findlocalminima(A)
3-element Vector{CartesianIndex{2}}:
CartesianIndex(2, 1)
CartesianIndex(4, 1)
CartesianIndex(2, 4)

julia> A[results]
3-element Vector{Int64}:
2
1
1

julia> LinearIndices(A)[results]
3-element Vector{Int64}:
2  # (2, 1) -> 2
4  # (4, 1) -> 1
14  # (2, 4) -> 1
``````
1 Like