MatLab function for each two values in struct inside loop

2 views (last 30 days)
Hello,
I have a struct with some fileds, (attached)
something like exp = {'Names', 'Date', 'X' , 'Y'}
Names = ['John', 'Adam', 'Markus',.....]
X = [ X1, X2, X3, X4,.....]
Y = [ Y1, Y2, Y3, Y4,.....]
I want to run an equation to calculate the sqrt for each two values depending on the same field (Date)
For Date (Date 1)
s12 = sqrt((X2-X1)^2+(Y2-Y1)^2);
then
s13= sqrt((X3-X1)^2+(Y3-Y1)^2);
and
s14= sqrt((X4-X1)^2+(Y4-Y1)^2);
and
s23 = sqrt((X3-X2)^2+(Y3-Y2)^2);
and
s24 = sqrt((X4-X2)^2+(Y4-Y2)^2);
and
s34 = sqrt((X4-X3)^2+(Y4-Y3)^2);
And the same for (Date2)
So I wrote a loop as follows:
for i= 1:length(example)
for j = i+1;
for u = 1:length(unique(example.dates,'rows'));
s(i) = sqrt((example(j).x-example(i).x)^2+(example(j).y-example(i).y)^2);
abr{i} = sprintf('%s-%s',strtrim(example(j).name),strtrim(example(i).name));
end
end
end
%%%%% Export results to an array (Date, Name i_Name j, S)
result = [];
for n = 1:length(unique(example.dates,'rows'));
result = [result; dates(n) abr(n) d(n)];
end
But I am sure there is something wrong because I should get s for all the pairs of the values and just for the same date each time.
The results should be something like that:
IMG_20190329_164539.jpg
Please help me to figure out how to do that.
  4 Comments
Luna
Luna on 29 Mar 2019
You have the same names and also same dates, are you sure that your name list will be unique for each date? Otherwise you will get a row like Ronny vs Ronny for example.
Mohammed Hammad
Mohammed Hammad on 29 Mar 2019
Edited: Mohammed Hammad on 29 Mar 2019
My names are unique for each date (without any duplications). And that's why I need my for loop to works for each date separately.

Sign in to comment.

Accepted Answer

Stephen23
Stephen23 on 29 Mar 2019
Edited: Stephen23 on 29 Mar 2019
load example.mat
C = {example.Name};
D = {example.dates};
M = [example.x;example.y];
[U,~,idu] = unique(D);
N = max(idu);
fprintf('%-12s %-10s %-10s %s\n','Date','Name1','Name2','Result')
for k = 1:N
idf = find(idu==k);
P = nchoosek(1:numel(idf),2);
V = sqrt(sum((M(:,idf(P(:,1)))-M(:,idf(P(:,2)))).^2,1));
T = [repmat(U(k),size(V));C(idf(P(:,1)));C(idf(P(:,2)));num2cell(V)];
fprintf('%-12s %-10s %-10s %#.5g\n',T{:});
end
Which prints this in the command window:
Date Name1 Name2 Result
02-Apr-2002 John Adam 4.8237e+06
02-Apr-2002 John Markus 6.7899e+06
02-Apr-2002 John Ronny 7.4859e+06
02-Apr-2002 John Michael 3.8794e+06
02-Apr-2002 Adam Markus 5.9770e+06
02-Apr-2002 Adam Ronny 6.6450e+06
02-Apr-2002 Adam Michael 4.7198e+06
02-Apr-2002 Markus Ronny 7.3046e+05
02-Apr-2002 Markus Michael 2.9522e+06
02-Apr-2002 Ronny Michael 3.6236e+06
03-Apr-2002 Ronny Markus 5.9770e+06
03-Apr-2002 Ronny Michael 6.6450e+06
03-Apr-2002 Ronny John 4.8237e+06
03-Apr-2002 Ronny Adam 4.7198e+06
03-Apr-2002 Ronny Romio 5.8499e+05
03-Apr-2002 Ronny Sebastian 7.4353e+06
03-Apr-2002 Markus Michael 7.3046e+05
03-Apr-2002 Markus John 6.7899e+06
03-Apr-2002 Markus Adam 2.9522e+06
03-Apr-2002 Markus Romio 6.1503e+06
03-Apr-2002 Markus Sebastian 1.0072e+07
03-Apr-2002 Michael John 7.4859e+06
03-Apr-2002 Michael Adam 3.6236e+06
03-Apr-2002 Michael Romio 6.8414e+06
03-Apr-2002 Michael Sebastian 1.0753e+07
03-Apr-2002 John Adam 3.8794e+06
03-Apr-2002 John Romio 4.3132e+06
03-Apr-2002 John Sebastian 3.3172e+06
03-Apr-2002 Adam Romio 4.6077e+06
03-Apr-2002 Adam Sebastian 7.1300e+06
03-Apr-2002 Romio Sebastian 6.8562e+06
>>
And checking the last one:
>> sqrt((example(11).x-example(12).x).^2 + (example(11).y-example(12).y).^2)
ans =
6.8562e+06
>> example(11:12).Name
ans =
Romio
ans =
Sebastian
>> example(11:12).dates
ans =
03-Apr-2002
ans =
03-Apr-2002
  7 Comments
Mohammed Hammad
Mohammed Hammad on 30 Mar 2019
Edited: Mohammed Hammad on 30 Mar 2019
due to the large data that I have and it's difficult to check whether that's everything is alright, I changed my data to be as follows:
Multiple cells, each cell contains the same data but each cell express one date (unique).
For example:
Cell (02-Apr-2002) contains Date, Name, X, Y, Z
Cell (03-Apr-2002) contains Date, Name, X, Y, Z
And So on...
And I loaded them into my workspace:
myFolder ='......';
filePattern = fullfile(myFolder, '*.mat');
theFiles = dir(filePattern);
Headings = {'Date', 'Name', 'X', 'Y', 'Z'};
for i=1:length(theFiles)
eval(['load ' theFiles(i).name]);
array = cell2struct(data, Headings, 2);
end
C = {example.Name};
D = {example.dates};
M = [example.x;example.y];
[U,~,idu] = unique(D);
N = max(idu);
fprintf('%-12s %-10s %-10s %s\n','Date','Name1','Name2','Result')
%%%%% how to perform the loop to works on each file and export Z for each date %%%%%%
for n = 1:length(theFiles)
for k = 1:N
idf = find(idu==N);
P = nchoosek(1:numel(idf),2);
V = sqrt(sum((M(:,idf(P(:,1)))-M(:,idf(P(:,2)))).^2,1));
T = [repmat(U(k),size(V));C(idf(P(:,1)));C(idf(P(:,2)));num2cell(V)];
fprintf('%-12s %-10s %-10s %#.5g\n',T{:});
Z{k} = T;
end
end
I apprciate your help always
And I tried to make it something like :
for i=1:length(theFiles)
eval(['load ' theFiles(i).name]);
array = cell2struct(data, Headings, 2);
C = {example.Name};
D = {example.dates};
M = [example.x;example.y];
[U,~,idu] = unique(D);
N = max(idu);
fprintf('%-12s %-10s %-10s %s\n','Date','Name1','Name2','Result')
%%%%% how to perform the loop to works on each file and export Z for each date %%%%%%
for k = 1:N
idf = find(idu==N);
P = nchoosek(1:numel(idf),2);
V = sqrt(sum((M(:,idf(P(:,1)))-M(:,idf(P(:,2)))).^2,1));
T = [repmat(U(k),size(V));C(idf(P(:,1)));C(idf(P(:,2)));num2cell(V)];
fprintf('%-12s %-10s %-10s %#.5g\n',T{:});
Z{k} = T;
end
end
It runs good for a while with showing for each date all the required results but it stopped and it said:
Error using nchoosek (line 65) K must be an integer between 0 and N.
PS: I have around 2500 cells.
Stephen23
Stephen23 on 31 Mar 2019
Edited: Stephen23 on 31 Mar 2019
@Mohammed Hammad: your code does not make much sense to me. In particular:
1. This loop:
for i=1:length(theFiles)
eval(['load ' theFiles(i).name]);
array = cell2struct(data, Headings, 2);
end
serves absolutely no purpose whatsoever, because you do not use any indexing (or concatenation) to store the output array, and so you simply overwrite array except for the one defined on the last iteration. So every previous iteration is just a waste of time. Also that eval usage should be avoided, which you can do very simply:
load(theFiles(i).name)
or even better:
S = load(theFiles(i).name);
array = cell2struct(S.data, Headings, 2);
2. You never use the variable array for anything anyway: once you have imported that data and created array you just ignore it. Seems like a waste of time to me!
3. For some reason you are still accessing a variable named example, although this is not defined anywhere in your code.
In any case that error message is very easy to understand: you will get that error whenever numel(idf)<2, i.e. there is only one name in the entire date group. If there is only one name (for a particular date) then clearly it is not possible to generate all combinations of two names from it! You will need to decide what to do in those cases (I cannot decide how your algorithm should work), but most likely you will need to add an IF condition, something like this:
Z = cell(1,N); % preallocate. Why did you remove this??? Very bad idea!
for k = 1:N
idf = find(idu==N);
if numel(idf)>1
... your code
Z{k} = T; % add data
else
... decide what you want to do with zero/one names.
end
end
Z = [Z{:}] % concatenate
Depending on how you decide to handle the one-name groups, you might need to use indexing for the concatenation as well.

Sign in to comment.

More Answers (0)

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Products


Release

R2019a

Community Treasure Hunt

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

Start Hunting!