When to use find, loops or if?

1 view (last 30 days)
Jenny
Jenny on 28 Sep 2011
I have a text file containing three columns of data (time in fractions of a day, depth, temp). I need code that will read through the data file and get an average temperature value for every 5 meter depth block in every half hour time block. Then place that result into a matrix (depth:time). I don't know what to use/how to structure it.
  2 Comments
Jan
Jan on 28 Sep 2011
What have you done so far?
Jenny
Jenny on 18 Oct 2011
This is what I've been able to come up with so far, but I get this error message: index exceeds matrix dimensions. I have checked the matrix I create in line 5, and it is the right size (I have done this by hand to have as a comparison). Any suggestions?
load('Swo86997PlotTempData.txt')
cmdata = Swo86997PlotTempData;
ch = [0:0.02083:0.70822];
rh = [0:5:420];
datfin = zeros(length(rh)-1, length(ch)-1)
for j = 1:(length(rh)-1);
for i = 1:(length(ch)-1);
st = rh(i) + ch(i);
en = rh(i+1) + ch(i+1);
[x] = find( cmdata(:, 1:2) >= st & cmdata(:, 1:2) < en );
datfin(j, i) = mean(cmdata(x,3));
end
end
dlmwrite('Swo86997PlotTempMatrix.txt',datfin, '\t')

Sign in to comment.

Accepted Answer

Matt Tearle
Matt Tearle on 18 Oct 2011
Two things I notice in your code:
  1. you're not using j to index into rh and ch -- is that intentional?
  2. find is returning linear indices from an n-by-2 matrix. This is probably what's causing the error. Your logical condition is testing an n-by-2 matrix, so find will return the non-zero locations as linear indices (ie between 1 and 2n), but you're using those indices (x) as a row index in the next line.
Can you show a few lines of data and what you'd like the result to be? There may well be a cleaner way to do this.
EDIT TO ADD: OK, based on what you've shown, this should do the job:
ch = 0:0.02083:0.70822;
rh = 0:5:420;
m = length(rh)-1;
n = length(ch)-1;
datfin = zeros(m, n);
for j = 1:n;
idx = (cmdata(:,1) >= ch(j)) & (cmdata(:,1) < ch(j+1));
x = cmdata(idx,:);
for i = 1:m;
idx = (x(:,2) >= rh(i)) & (x(:,2) < rh(i+1));
datfin(i, j) = mean(x(idx,3));
end
end
A couple of things, though... Here's the first bit of output I get:
6.2000 NaN
7.4000 2.4500
4.2500 NaN
6.2333 8.5000
6.1000 2.9500
NaN 6.2500
NaN 3.4000
8.5000 3.9833
The second column is what you calculated by hand, but the first column is off. The (1,1) element should be the mean of the values in the third column where the first column is in the range [0,0.0283) and the second is in the range [0,5), right? The only entry I can see that fits that is the third row (0.002070473 1.6 6.2), so the mean of 6.2 looks right -- I don't understand how you got 5.4. Can you clarify?
Also, is your data ordered by the first column? If so, you might be able to speed up the algorithm by avoiding doing the full logical comparisons for every j. If it's not too slow as is, though, I wouldn't bother.
  1 Comment
Jenny
Jenny on 18 Oct 2011
For #1, that was a mistake, I think it should use j to index into rh and i to index into ch.
For #2, what I am trying to do is find all values in column 3 who's corresponding row values in columns 1 and 2 meet the criteria of being equal to or greater than ch(i) and rh(j), respectively, but less than ch(j+1) and rh(j+1). So maybe those lines should be st = rh(j) & ch(i) and en = rh(j+1) & ch(i+1). I don't want to actually add those values together.
Example data is below.
randomly generated input data
timestamp, depth, temp
0 53.5 5.4
0.001035237 14.82 5
0.002070473 1.6 6.2
0.00310571 12.8 3.5
0.004140946 49.5 8.2
0.005176183 18.4 4.9
0.00621142 36.6 8.5
0.007246656 16.5 8.1
0.008281893 9.1 9.5
0.009467593 21.66 7.1
0.010502829 53.8 0.5
0.011538066 46.6 7.5
0.012573302 24.5 5.1
0.013608539 41.1 7.2
0.014643776 18.1 5.7
0.015679012 46.1 1.1
0.016714249 5.4 5.6
0.017749486 50.18 5.2
0.018819444 7.9 7.1
0.019854681 44.5 8.5
0.020889918 36.2 8.3
0.021925154 9.7 3.4
0.022960391 46.2 8.1
0.023995628 7.9 1.5
0.025030864 24.2 2.6
0.026066101 19 8.5
0.027101337 28.1 9.2
0.028159722 33.8 3.4
0.029194959 20.9 3.3
0.030230195 38.7 0.5
0.031265432 49.1 6.4
0.032300669 26.3 4.5
0.033335905 58.2 4.1
0.034371142 29.6 5
0.035406379 41.7 6.4
0.036441615 53.8 8.4
0.037488426 39 5.4
0.038523663 36.3 4.9
0.039558899 36 2.6
0.040594136 27.9 6.3
0.041629372 35.3 2.2
output data calculated by hand(first row & column are labels)
0 0.02083
0 5.4 nan
5 4.9 2.5
10 6.6 nan
15 8.7 8.5
20 3.8 3.0
25 nan 6.3
30 nan 3.4
35 7.5 4.0
40 6.2 6.4
45 4.1 7.3
50 6.9 8.4
55 nan 4.1
row labels are depth, column labels are time in fractions of a day

Sign in to comment.

More Answers (3)

Grzegorz Knor
Grzegorz Knor on 28 Sep 2011
Start solve your task by reading this topic:
Then you will need the mean function and some matrix indexing:

Jenny
Jenny on 14 Oct 2011
This is what I've been able to come up with so far, but I get this error message: index exceeds matrix dimensions. I have checked the matrix I create in line 5, and it is the right size (I have done this by hand to have as a comparison). Any suggestions?
load('Swo86997PlotTempData.txt')
cmdata = Swo86997PlotTempData;
ch = [0:0.02083:0.70822];
rh = [0:5:420];
datfin = zeros(length(rh)-1, length(ch)-1)
for j = 1:length(rh-1);
for i = 1:(length(ch)-1);
st = rh(i) + ch(i);
en = rh(i+1) + ch(i+1);
[x] = find( cmdata(:, 1:2) >= st & cmdata(:, 1:2) < en );
datfin(j, i) = mean(cmdata(x,3));
end
end
dlmwrite('Swo86997PlotTempMatrix.txt',datfin, '\t')
  1 Comment
Jenny
Jenny on 14 Oct 2011
line 6 should be
for j = 1:(length(rh)-1);

Sign in to comment.


Jenny
Jenny on 19 Oct 2011
Matt - I went back and re-calculated the matrix by hand and got the same thing your code got. I made a mistake somewhere the first time. The code you suggested works perfectly. The only addition necessary was a line to change any - depth data in the source file to + values. Thank you so much for your help.

Categories

Find more on Data Distribution Plots in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!