user2324712
user2324712

Reputation: 435

Make this matlab code run without a for loop

  1. Lets say that I have an array x with some data values.
  2. I performed a clustering algorithm that has produced a label map with the label names - labelMap. Each point in the data now has a unique cluster label associated to it.
  3. I then perform the function foo(subset, secondArg) over each subset. The function foo returns a new array with the result which has the same size as its given the argument (its a map() function which also recieves a second argument).

What follows is the current implementation:

    x = rand(1,1000);
    numClusters = 3; % specified in advance by the user, for example using a clustering algorithm such as K-Means, this is a given.
    fooSecondArg = [1,2,3]; % second argument for foo().

    labelMap = kmeans(x,numClusters);
    res = zeros(size(x));

    %% make me run without a for loop :)
    for ind = 1:numClusters
        res(labelMap == ind) = foo(x(labelMap == ind), fooSecondArg(ind));
    end

My question is as follows:

As there is no overlap between the indices in x foo() acts upon, is there a way to perform foo over x without using a for or a parfor loop? (I don't want to use a parfor loop as It takes quite a while to start the additional matlab processes and I cannot later on deploy it as a stand alone application).

Many thanks!

Edit: I was asked for an example of foo() because I was told the solution may depend on it. A good viable example you may use in your answer:

    function out = foo(x,secondArg)
    out = x.^2/secondArg;

Upvotes: 1

Views: 86

Answers (1)

Luis Mendo
Luis Mendo

Reputation: 112659

Whether the loop can be removed or not depends on the function you have. In your case the function is

function out = foo(x,secondArg)
out = x.^2/secondArg;

where secondArg depends on the cluster.

For this function (and for similar ones) you can indeed eliminate the loop as follows:

res = x.^2 ./ fooSecondArg(labelMap);

Here

  • labelMap is the same size of x (indicates the cluster label for each entry of x);
  • fooSecondArg is a vector of length equal to the number of clusters (indicates the second argument for each cluster).

Thus fooSecondArg(labelMap) is an array the same size of x, which for each point gives the second argument corresponding to that point's cluster. The operator ./ performs element-wise division to produce the desired result.

Upvotes: 1

Related Questions