How to write such a loop?

Hello everybody, I have two data vectors: d1 and d2, I have passed them through a segmentation algorithm, and the resulted class indexes are IDX1 and IDX2. Number of members in each segment are segMem1 for d1 and segMem2 for d2. Now I want to assign one index to each component in d1 (and d2), according to segMem1 (and segMem2). Moe specifically, I want to index the 3 first components of d1 as 1 1 1, the two next components as 2 2 , the 2 third components as 1 1 and so on, and at last I want to have 1 1 1 2 2 1 1 3 4 4 for d1. I have written the following code, and it seems to work for indexing d1. But I don't know how to make another loop to generalize this to both d1 and d2?
clear all
close all
clc
% data
d1 = [10 3 44 33 4 16 7 10 22 54];
d2 = [3 24 35 12 3 4 7];
IDX1 = [1 2 1 3 4];
IDX2 = [3 1 2 1];
segMem1 = [3 2 2 1 2]; % Determines how many times each index in IDX1 should be repeated.
segMem2 = [2 1 2 2];
%%Now assign indexes to data vector
n = 1;
a = cell(1,length(d1));
for k = 1:length(segMem1)
for j = n:segMem1(k)+n-1
a{j} = IDX1(k);
end
n = n+segMem1(k);
end
Any help would be greatly appreciated.

9 Comments

If IDX1 is a list of the class indexes that the elements of d1 belong to, then IDX1 should have the same number of elements. So IDX1(1) says that d1(1) belongs to class 1, and IDX1(2) says that d1(2) belongs to class 2, and IDX1(3) says that d1(3) belongs to class 1, etc. So why does your IDX1 have only 5 elements instead of 10? Which elements of d1 have their classes specified by IDX1, and which do not and are missing?
Next you say "Number of members in each segment are segMem1 for d1...." but we can see that segMem1(1) is 3 but we can see from IDX1(1) that the first class shows up two timed, not 3. Just look at IDX1 - there are 2 ones in it, not 3 meaning that 2 elements of d1 were labeled as being in class 1.
So I'm confused by your explanation and need more clarification.
dpb
dpb on 18 Jan 2015
Ayup...same things I thought (but was too lazy to enumerate :) )...
Im sorry maybe I tried my best to explain, but it seems I was not. Lets clarify d1 and IDX1 and segMem1. After segmentation ,what I have are 5 segments in d1. segMem1 shows how many components are in each segment: segMem1(1) = 3, so d1(1:3) i.e. 10, 3 and 44 are making the first segment. These three should be indexed as IDX1(1). Next: segMem1(2) = 2, so two next components of d1 ie 33 and 4 are located in this segment, and their index would be IDX1(2) = 2. Next : segMem1(3)=2, so next segment consists of two members, namely 16 and 7 with IDX1(3)=1 as their index. the next segment, has just one member, since segMem1(4)=1 and it is indexed by 3. the last segment has 2 members, 22 and 54, these to be labeled by IDX1(5)=4.
Long story made short, what this code is supposed to do, is to distribute the IDX1 according to segMem1: IDX1(1) should be repeated 3 times, as segMem1(1)=3, IDX1(2) should be repeated 2 times, as segMem1(2)=2 and so on
If you run the code, you will see how it works for d1. My problem is to generalize it, as actually I have 3696 segMem and IDX matrices and for each segMem, IDX should be distributed as described above.
dpb
dpb on 18 Jan 2015
Wrong answer!!! Don't expect us to try to debug non-working code; gives us the actual algorithm to try to implement.
Im sorry but I don't know what you mean by non-working code! Its working fine at my pc, by fine I mean it gives the results for d1. Its where Im stuck: I can not make it done for more than one data vector.
dpb
dpb on 18 Jan 2015
...I can not make it done for more than one data vector.
Then it doesn't work, does it? If it did, you wouldn't have a problem.
"Houston, we have a problem" in that the algorithm isn't well-enough defined by your initial description from which to write a piece of code. It's quite possible the actual solution is far removed from your first pass and the only practical way to attack it is to know the requirements first, not to try to guess how to hack on a given piece of code without answers to the questions posed by IA...
You are right dpb, I made a mistake in my description. But I tried to explain it in next comments. anyways, I try once more: IDX1 contains indexes after classification. so d1 is divided into 5 segments, and classified into 4 classes(to be labeled as 1,2,3,4): d1 = [10 3 44|33 4|16 7|10| 22 54]; where the vertical bar (|) shows the segment boundaries. Now I want IDX1 to be distributed according to segMem1: I mean I want IDX1 to be: [1 1 1 | 2 2 |1 1 |3 |4 4] I hope its now clear why IDX1 has five elements, while d1 has 10. Thank you for taking the time.

Sign in to comment.

 Accepted Answer

dpb
dpb on 18 Jan 2015
Edited: dpb on 18 Jan 2015
>> cell2mat(arrayfun(@(x,y) repmat(x,y,1),IDX1,segMem1,'uniform',0).')
ans =
1
1
1
2
2
1
1
3
4
4
>>
Since Matlab doesn't know about jagged arrays other than by cell array, you'll have to build the pieces and rearrange them into a cell array.
Oh, a spurious thought though I've never tried it; I suppose one could wrap a cellfun call around arrayfun, maybe to process the two cells as you've smushed them together above; otherwise a loop or the cell array.
ADDENDUM
OK, the looping construction works well enough...
>> for i=1:length(IDX)
idx=IDX{i};
seg=s{i};
cell2mat(arrayfun(@(x,y) repmat(x,1,y),idx,seg,'uniform',0))
end
ans =
1 1 1 2 2 1 1 3 4 4
ans =
3 3 1 2 2 1 1
>>
Left as row vectors for more compact display...

1 Comment

Thank you so much dpb, just working great ! You made my day! :)

Sign in to comment.

More Answers (1)

Negar
Negar on 18 Jan 2015
Edited: Negar on 18 Jan 2015
I tried to make it for 2 data vectors, as follows:
clear all
close all
clc
% data
d1 = [10 3 44 33 4 16 7 10 22 54];
d2 = [3 24 35 12 3 4 7];
IDX1 = [1 2 1 3 4];
IDX2 = [3 1 2 1];
segMem1 = [3 2 2 1 2]; % Determines how many times each index in IDX1 should be repeated.
segMem2 = [2 1 2 2];
s = {segMem1 segMem2};
IDX = {IDX1 IDX2};
nData = 2 % 2 data vectors
%%Now assign indexes to data vector
n = 1;
a = cell(2,1);
for i = 1:nData
for k = 1:length(s{i})
for j = n:s{i}(k)+n-1
a{j,i}(k) = IDX{i}(k);
end
n = n+s{i}(k);
end
n = 1;
end
When running this code, I get all elements of the cell 'a' as doubles:
a =
1 3
1 3
1 [0,1]
[0,2] [0,0,2]
[0,2] [0,0,2]
[0,0,1] [0,0,0,1]
[0,0,1] [0,0,0,1]
[0,0,0,3] []
[0,0,0,0,4] []
[0,0,0,0,4] []
Could anyone suggest what I should do in order to have all elements as scalars? like
a =
1 3
1 3
1 1
2 2
2 2
1 1
1 1
3
4
4

Categories

Tags

Asked:

on 18 Jan 2015

Commented:

on 18 Jan 2015

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!