Info

This question is closed. Reopen it to edit or answer.

Are the if statement conditions I have implemented identifying the correct data?

1 view (last 30 days)
I am unsure whether or not the if statement I have implemented is identifying the correct data.
Basically, I only want the program to consider the slope of a line for which the wind direction is between 0 and 45 degrees and if the wind speed is between 0 and 50 meters per second for all heights. Then I would like to find the average of all valid slopes.
Is my code meeting these criteria?
Thanks!
kane = 'Kane_Data_Splice.xlsx';
Height = [19 44 69 90 148]; %Height at which measurement was taken
Speed = [xlsread(kane,'BA:BA') xlsread(kane,'AS:AS') xlsread(kane,'AK:AK') xlsread(kane,'AC:AC') xlsread(kane,'U:U')]; %Wind speed at corresponding height
Direction = xlsread(kane,'T:T'); %Wind direction, same for all heights
n = numel(Direction);
counter = 1;
m1 = zeros(1, n);
m2 = zeros(1, n);
m3 = zeros(1, n);
m4 = zeros(1, n);
m5 = zeros(1, n);
m6 = zeros(1, n);
m7 = zeros(1, n);
m8 = zeros(1, n);
for i = 1:n
if (0 < Direction(i)) && (Direction(i) < 45) && (0 < Speed(i)) && (Speed(i) < 50)
p = repmat(log(Height),n,1);
q = log(Speed);
x = p(i,:);
y = q(i,:);
line = polyfit(x,y,1);
m1(counter) = line(1);
counter = counter + 1;
end
end
Alpha_Quad_1 = mean(m1)

Answers (2)

the cyclist
the cyclist on 27 Feb 2015
Assuming that the units in the file are the same as the ones you want, the code looks right to me. Do you have a reason to doubt it?
  1 Comment
dpb
dpb on 27 Feb 2015
Using the short-circuiting operator works only because the loop is on a single element. I'd recommend against it as general practice for the purpose as it will bite if used for selection over a group at a time by short circuiting.

dpb
dpb on 27 Feb 2015
Edited: dpb on 1 Mar 2015
Having done it via a loop it works but you should--
  • vectorize, and
  • not use short-circuit operator
Here's where a little "syntactic sugar" is handy to make the higher level code easier to read...
If define
function flg=isbetween(x,lo,hi)
% returns T for values within range of input
% SYNTAX:
% [log] = isbetween(x,lo,hi)
% returns T for x between lo and hi values, exclusive
flg= (x>lo) & (x<hi);
then can write your above as
idx=isbetween(Direction,0,45) & isbetween(Speed,0,50); % select the desired elements
I've a couple/three of these, another I use regularly is iswithin which is identical except for being inclusive. There's another with optional additional arguments to control either end as desired.
Anyway, with that you can return the rows desired as
x=p(idx,:);
y=q(idx,:);
and iterate over those. Unfortunately, polyfit doesn't work on a vectorized basis and arrayfun works on a per element basis instead of by column or row so have to become a little more creative to vectorize the rest of the computation.
coeff=cell2mat(accumarray([1:n].',[1:n].',[], ...
@(i) {polyfit(x(:,i),y(:,i),1)}));
slope=coeff(:,1);
It needs a little more thought than I have time to spare at the moment to work out the multiple angles portion but should give the idea.
But, other than using & instead of && the logic is correct altho I firmly believe the clarity of the illustrated helper functions is worth using them. And, of course, you can use them in the loop, too...
if isbetween(Direction(i),0,45) & isbetween(Speed(i),0,50)
...
ADDENDUM
Had a little time; came back to see if could get thru the whole thing...removing redundant unused mN arrays and the unneeded replication of the height vector then moving loop-invariant stuff outside the loop we have...
...
n = numel(Direction);
counter = 1;
m1 = zeros(1, n);
x = log(Height);
q = log(Speed);
for i = 1:n
if isbetween(Direction(i),0,45) & isbetween(Speed(i),0,50)
y = q(i,:);
line = polyfit(x,y,1);
m1(counter) = line(1);
counter = counter + 1;
end
end
Alpha_Quad_1 = mean(m1)
ERRATUM/ADDENDUM There's a bug in the above that just caught my attention-- counter is initialized to 1 prior to the if test and incremented inside the conditional prior to the next loop. Consequently, after the loop completes, n is one greater than the number of elements found. This isn't a problem if (but only if) there are no missing elements. However, if counter<=n when finish the loop, then the computed mean will include the zero elements in the preallocated array m1 of length n. Need to include a fixup if use the above looping solution to account for the possibility--
m1(counter:end)=[]; % eliminate unused elements
Now one can compute the mean correctly.
A cleaner solution keeping the looping construct would be to initialize to 0 and then only increment inside the conditional branch. If use nan() to preallocate, then nanmean would also alleviate the need for the length fixup.
END ERRATUM NOTE
OK, now with a little more time I see the data structure and what's wanted more clearly...looks like what did before is essentially correct; the logical vector of conditions being within the desired range ensures the only values returned will be those for which counter would otherwise have been incremented and the multiple m arrays were apparently a leftover from previous thinking needed to accumulate multiple sums by octants or somesuch. Anyway, what there is in the end is an Nx5 array of wind Speeds which are to be fitted against height for observations in the desired direction band and under a limit so indeed the previous is ok if use the two log'ed values. My suggested final solution would look like--
idx=isbetween(Direction,0,45) & isbetween(Speed,0,50);
x = log(Height);
y = log(Speed(idx,:)); % select the subset
N = sum(idx); % number found
coeff=cell2mat(accumarray([1:N].',[1:N].',[], ...
@(i) {polyfit(x,y(:,i),1)}));
Alpha_Quad_1 = mean(coeff(:,1));

Community Treasure Hunt

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

Start Hunting!