extract user defined data from matrix in GUI

1 view (last 30 days)
JB
JB on 5 Oct 2017
Commented: Jan on 9 Oct 2017
This might be a simple question but I still need some help to sort this out. I have Dataset and from this the user defines which columns to extract from a uitable. I can get the uitable data which will look like the "sample" below:
Dataset =
1 2 3 4 5 6
5 6 7 8 9 10
10 20 30 40 50 60
100 200 300 400 500 600
sample =
1 3 0
2 4 6
Now I want to extract the columns specified in each "sample" row of the Dataset and calculate the mean and finally create a new matrix with then calculated means in each column. The result would be:
new =
2 4
6 8
20 40
200 400
Sorry for the clumsy description, but I hope I makes sense. But any help is very appreciated. The above example is a simplified example. The Dataset I ahve is very large andso is the "sample" set (many rows x 3 columns),so I believe a loop will solve the issue but please let me know if you have other ideas. Thanks
  2 Comments
Jan
Jan on 5 Oct 2017
I read the question 5 times now, without understanding it. You want to extract columns from matrix DataSet. These columns are "specified in each row of sample". The first row is [1,3,0]. Perhaps this means the 1st and 3rd column of DataSet. But then the mean would be [2, 6, 20, 200]. Is the leading 1 a typo?
Now the 2nd row: [2,4,6]. The corresponding columns are:
2 4 6
6 8 10
20 40 60
200 400 600
And again the mean is not [4, 12, 40, 400], but the 2nd element would be 8.
Please clarify this.
JB
JB on 5 Oct 2017
Hi Jan Simon. You are absolutely right. I have corrected in the question above. Thanks a lot.

Sign in to comment.

Answers (1)

Jan
Jan on 5 Oct 2017
Edited: Jan on 5 Oct 2017
DataSet = [ ...
1 2 3 4 5 6; ...
5 6 7 8 9 10; ...
10 20 30 40 50 60; ...
100 200 300 400 500 600];
sample = [1 3 0; ...
2 4 6];
nSample = size(sample, 1);
Avg = zeros(size(DataSet, 1), nSample);
for k = 1:nSample
index = sample(k, :);
index = index(index ~= 0);
Avg(:, k) = sum(DataSet(:, index), 2) / numel(index); % Faster than mean()
end
Does this produce the wanted output? If so, let's think of vectorizing this:
wData = size(DataSet, 1);
[nSample, wSample] = size(sample);
nValidSample = sum(sample ~= 0, 2).';
% Insert a column of zeros to handle the 0 in sample:
DataPad = cat(2, zeros(wData, 1), DataSet);
% Shift the indices in sample and use them as column index:
Sampled = DataPad(:, sample.' + 1);
% Create blocks to sum over:
Sampled = reshape(Sampled, wData, wSample, nSample);
% Average over blocks: (! Auto-Expand, >= R2016b !)
Avg = reshape(sum(Sampled, 2), wData, nSample) ./ nValidSample;
For older Matlab versions the last line is slightly slower:
Summed = reshape(sum(Sampled, 2), wData, nSample);
Avg = bsxfun(@rdivide, Summed, nValidSample);
A speed comparison (R2016b/64):
DataSet = rand(4, 1e3);
sample = randi([0, 1e3], 1e6, 3);
Loop: 6.46 sec
Vectorized: 0.36 sec
  3 Comments
Jan
Jan on 9 Oct 2017
Copied from the section for answers: [JB wrote:]
@Jan Simon. Once again thanks a lot for your great help. I am working with MATLAB R2015b/32 and get an error in the last code line:
Error using ./ Matrix dimensions must agree.
Am i making a mistake or???
Jan
Jan on 9 Oct 2017
Please read my answer carefully. I repeat:
% Average over blocks: (! Auto-Expand, *** >= R2016b *** !)
Avg = reshape(sum(Sampled, 2), wData, nSample) ./ nValidSample;
For older Matlab versions the last line is slightly slower:
Summed = reshape(sum(Sampled, 2), wData, nSample);
Avg = bsxfun(@rdivide, Summed, nValidSample);

Sign in to comment.

Categories

Find more on Specifying Target for Graphics Output in Help Center and File Exchange

Tags

Products

Community Treasure Hunt

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

Start Hunting!