How to write array results of variable length to zeros matrix matrix?

Hi!
I'm trying to find the most efficient way to write arrays to a zeros matrix. I have another function that creates the array, now I'm just trying to figure out the most efficient way to store it in a matrix. I also need to lag the arrays by 1 column and 1 row for subsequent arrays as well. For those of you who are familiar with Unit Hydrograph convolution, that's what I'm doing. The reason I need this to be as fast as possible is because I'm going to be running this code for like 20,000 time steps. Also, I should mention I'm a Matlab Noob.
Here's the array I've already calculated:
I want to put it in this zeros matrix:
What I want to output is this:
The reason I need to put the arrays in a matrix is because I need to sum all of the rows across the columns and place into a new array. I should also mention that the arrays might be variable lengths and not all will be the same magnitude, as shown here, during actual implementation of the code depending on the storm event.
Thanks for any help you can provide!

4 Comments

"The reason I need to put the arrays in a matrix is because I need to sum all of the columns"
The sum of each column would be the same. Why not just do this? (r2016b or later)
sum(vector).*[1,1,1,1]
Also, the first value of the column vector is 0 but I don't see that value represented in the example output. Instead, the last non-zero value of the vector changes in the example output.
Whoops - I mean sum rows across the columns. I will edit.
Also it looks like the picture of the output is slightly incorrect as you pointed out. The first value should be zero.
My answer should solve the problem. If not, please elaborate.

Sign in to comment.

 Accepted Answer

From the example inputs/outputs given in the quesiton, I don't know what's happening to the first 0 at index 1 which doesn't appear in the outputs. I also don't know where the last non-zero value in the output comes from since it differs from the last non-zero value in the input.
Assuming this is an error, here's how to produce that matrix using circshift.
data = [rand(25,1);0;0;0]; % input vector
M = cell2mat(arrayfun(@(i){circshift(data(:),i)},0:3));% output matrix
To get the sum of each row,
sum(M,2)
It also may be useful for you to explore the movsum() function.

10 Comments

Thanks Adam. This is getting super close. The only problem I'm having now is that array is actually going to change from time step to timestep. i.e., I will need to calculate a new "data" array for each new time step and write those to the matrix.
The 'data' array is just an example input. If you want to make the 2nd line into a function,
vec2mat = @(data)cell2mat(arrayfun(@(i){circshift(data(:),i)},0:3));
Now you can input any variable you want.
M1 = vec2mat(vector1)
M2 = vec2mat(vector2)
% etc...
If the number of columns of the output is expected to change, you'll need to describe the rule that determines the number of columns. That would be an easy fix which you may be able to figure out on your own.
Thanks Adam. I'm playing around with it to try to get it to work with this application. By the by, here's what I was referring to when I mentioned that the arrays could be different. Thanks for your help here!!!
It looks like it's working well, no?
If you want table format,
T = array2table([M,sum(M,2)],'VariableNames', ...
{'UH1', 'UH2', 'UH3', 'UH4', 'Sum'}, ...
'RowNames', strsplit(num2str((0:size(M,1)-1))))
Example of first few rows (random data)
T =
28×5 table
UH1 UH2 UH3 UH4 Sum
________ ________ ________ ________ _______
0 0.73839 0 0 0 0.73839
1 0.29456 0.73839 0 0 1.0329
2 0.3131 0.29456 0.73839 0 1.346
3 0.59024 0.3131 0.29456 0.73839 1.9363
4 0.75829 0.59024 0.3131 0.29456 1.9562
I think it's it working! The only problem I see is that this will be repeated like 20,000 times, so eventually it will be UH20,000. Unless I am missing something from your thoughts beforehand?
I just timed this
data = [rand(25,1);0;0;0]; % input vector
tic
M = cell2mat(arrayfun(@(i){circshift(data(:),i)},0:19999));
% ^^^^^^^^ 20k columns
toc
and the result is
Elapsed time is 0.293079 seconds.
>> size(M)
ans =
28 20000
To create 20k column headers,
strsplit(strtrim(sprintf('UH%d ', 1:20000)))
Thanks Adam. I guess at this point I'm just having trouble iterating the columns with differing arrays (in your function, this would be equal to a 25 new random data points for each column).
I don't follow. Could you illustrate the problem somehow?
Hi Adam,
I ended up changing the code, but it worked out. Here's how we were able to get this done. The end result is just an array of the summed matrix.
Thanks again for your help!
% read in peak runoff
n = length(Hbd);
Interflow = zeros(n,1);
% Read in Hbd
for j = 1:n
HbdIn=Hbd(j);
% Run the baseflow code
Base = BaseflowInterflowUH(HbdIn,5,10000,0.7);
% Add together interflow into one time series
Interflow([j:lastReplace],1)=Interflow([j:lastReplace],1)+Base([1:lastBase],1);
end

Sign in to comment.

More Answers (0)

Categories

Products

Release

R2016b

Asked:

on 23 Apr 2020

Edited:

on 3 Nov 2020

Community Treasure Hunt

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

Start Hunting!