Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Average value of range of vector elements

Asked by Tim Skov Jacobsen on 19 Sep 2013

I have a huge amount of data with time stamps concerning temperature and displacement of a bridge deck.

I want to look at hourly intervals and have therefore assigned all the time stamps to their corresponding hour starting from a specific point in time, namely 1/1-2013 00:00.

To clarify:

  • from 1/1-2013 00:00 to 1/1-2013 00:59 => hour number 0
  • from 1/1-2013 01:00 to 1/1-2013 01:59 => hour number 1
  • ...
  • from 1/1-2013 07:00 to 1/1-2013 07:59 => hour number 7

This means that my data vectors now look like this:

if true  (this is the only way I could find to make the following in vector form)         
end
Time[h]        Temperature[deg C]        Displacement[cm]
0                 5.45                       0.133
0                 5.57                       0.136
0                 5.68                       0.140
1                 6.02                       0.145          
1                 6.24                       0.147
2                 6.56                       0.149
2                 6.78                       0.152
2                 6.76                       0.152
2                 6.80                       0.153
...                ....                       .....

Since I want to plot the relationship between temperature and displacement with hourly time steps, I would like to compute the mean value of every hour. This should go into a new vector containing only the hourly averaged time stamps.

My problem is that every hour has a different amount of data points, e.g. hour 0 has three, hour 1 has two and hour 2 has four. How do I go about this without making loops? I imagine that a vectorized method would save a lot of running time compared to loops.

The result I want should look something like the following:

if true  (this is the only way I could find to make the following in vector form)         
end
Time[h]        Temperature[deg C]        Displacement[cm]
0                 5.57                       0.136
1                 6.13                       0.146          
2                 6.73                       0.152
...                ....                       .....

I hope that I made the problem clear, otherwise I would be happy to elaborate.

Thanks in advance.

Tim

2 Comments

Jan Simon on 19 Sep 2013

Your tables are nice. For suggesting a solution, it would be helpful, if you explain in which format your data are available. Is this a struct, cell array, 3 different vectors?

Tim Skov Jacobsen on 19 Sep 2013

Thanks! I have the data in excel, but have imported them into 3 different vectors in Matlab.

Tim Skov Jacobsen

Products

No products are associated with this question.

2 Answers

Answer by Jan Simon on 19 Sep 2013
Edited by Jan Simon on 19 Sep 2013
Accepted answer

This is a perfect job for accumarray:

avgTemperature = accumarray(Time + 1, Temperature, [], @mean);

Unfortunately I have severe problems to understand the documentation of this command. Because I do not have access to Matlab currently, I can only guess, if the shown method is working.

[EDITED] Although accumarray allows a very compact solution, here a simple FOR loop:

Time1   = Time + 1;    % No zeros as indices
n       = length(Time1);
maxTime = max(Time1);
accum   = zeros(1, maxTime);
len     = zeros(1, maxTime);
for k = 1:n
  index = Time1(k);
  accum(index) = accum(index) + Temperature(k);
  len(index)   = len(index)   + 1;
end
result = accum ./ len;

(Not tested, typos might exist)

6 Comments

Jan Simon on 19 Sep 2013

@Tim: Please post your code here.

Andrei Bobrov on 19 Sep 2013
   z = [0                 5.45                       0.133
   0                 5.57                       0.136
   0                 5.68                       0.140
   1                 6.02                       0.145
   1                 6.24                       0.147
   2                 6.56                       0.149
   2                 6.78                       0.152
   2                 6.76                       0.152
   2                 6.80                       0.153]
   [ii jj] = ndgrid(z(:,1)+1,1:size(z,2)-1)
   z23 = z(:,2:end)
   out = [unique(z(:,1)),accumarray([ii(:),jj(:)],z23(:),[],@mean)
Tim Skov Jacobsen on 19 Sep 2013

The best and simplest way I found to compute the average of all data points within each time step is the following:

Vector description:

  • d - displacement vector
  • h - vector of hour numbers (see original post for clarification)
   datasum = accumarray(h,d); % sum of all data point within each time step
   indices = ones(size(h));   % indices for summing data point count
   datacount = accumarray(h,indices); % count of data points within each   time step
   mean = datasum./datacount; % average data value within each time step

The trick here is really the accumarray function, which is a kind of a conditional summation of vector components. What made me understand this function correctly was this article: http://blogs.mathworks.com/loren/2008/02/20/under-appreciated-accumarray/

Jan Simon
Answer by Image Analyst on 19 Sep 2013

I remember this was answered before, maybe a year ago or so. I don't remember anything to search about it. On the other hand, this is fairly easy with the Image Processing Toolbox. The time is your "labels" and you just call regionprops() on each column to get the values of each label (time). Then sum up and divide by the number in each label. Do you have the Image Processing Toolbox?

3 Comments

Tim Skov Jacobsen on 19 Sep 2013

I tried to search but did not find anything that relevant. I only have a Matlab license from the university. I have never tried the Image Processing Toolbox, does it come with the standard Matlab or is it a separate program?

Image Analyst on 19 Sep 2013

Type "ver" on the command line to see what toolboxes are installed. Code using regionprops would go something like (untested):

measurements = regionprops(times, temperatures, 'Area', 'EulerNumber');
meanTempValues = [measurements.Area] ./ [measurements.EulerNumber];

The times and temperatures are assumed to already be extracted into 1D row or column vectors:

times = array2D(:,1);
temperatures = array2D(:, 2);
displacements = array2D(:, 3);

so do that first if you need to. Similarly, call regionprops() again to get the mean displacements over the hours.

measurements = regionprops(times, displacements, 'Area', 'EulerNumber');
meanDispValues = [measurements.Area] ./ [measurements.EulerNumber];
Tim Skov Jacobsen on 19 Sep 2013

Since I am not familiar with this toolbox I think I will go with the accumarray approach as described above. Thank you very much for your input though.

Image Analyst

Contact us