Beginners MATLAB question
I have 4 variables(beam1,beam2,beam3,beam4) in separate arrays with the same dimensions (23746 x 35). I want to calculate the average of the 4 arrays to have an answer in one array with the same size (23746 x 35). In other words I want to average the values in the first dimension.
x = beam1,beam2,beam3,beam4
xx = mean(x,1)
Gives a 1x35 array and
x = beam1,beam2,beam3,beam4
xx = mean(x,2)
Gives a 23746x1 array
How do I keep the same dimensions (23746 x 35) in the new array and compute the average value of the 4 individual arrays?
Many thanks
Doesn't simply doing
xx = (beam1 + beam2 + beam3 + beam4)/4
give what you want?
Note that it's typically bad practice to have variable names that only differ by an appended integer such as you have. You've be better creating the data as a 3-dimenional array where
beam_data = beam1;
beam_data(:,:,2) = beam2;
beam_data(:,:,3) = beam3;
beam_data(:,:,4) = beam4;
In this way if you have more (or less) beams then you don't have a proliferation of variables.
It also means irrespective of how many beams you have the mean would be calculates along the 3rd dimension
beam_mean = mean(beam_data,3);
Related
Let's say I have 5 arrays of different sizes. All of the arrays have the same number of columns, in my case 2, but a different number of rows. I need to find the elements of the rows that appear in at least 3 of such arrays.
Right now, I compare two arrays using ismember, then compare that result with the third array and then save the row values which occur in all the three arrays. I do this for every possible combination of 3 arrays; basically in my case, I have 10 of such operations in total. It's like choosing three out of 5 without repetitions.
It works, but I am looking for a more efficient implementation. In particular, I was looking for any implementation that can perform this by voting. It's like having sets of different sizes and trying to find the elements that appear in the majority of sets, in my case 3 arrays out of 5.
Not sure what you mean by voting but I think does what you are looking for.
It creates 1 big unique matrix of all the rows from the arrays. The does an ismember by rows of the unique array with each individual array. The ismember is summed together to get a count of how many times each unique row exists across your set of arrays.
You can then use that count to return a new array that has at least minNum occurrences.
You would call it like this:
>> [outRows, uRows, memCount]= getRowDuplicates(3,a,b,c,d,e)
Where a,b,c,d,e are you arrays and 3 is the minimum number of occurrences
function [outRows, uRows, memCount]= getRowDuplicates(minNum,varargin)
uRows = unique(vertcat(varargin{:}),'rows');
memCount = false(size(uRows,1),1);
for j = 1:nargin-1
memCount = memCount + ismember(uRows,varargin{j},'rows');
end
rowIdx = memCount >= minNum;
outRows = uRows(rowIdx,:);
Thanks to Aero Engy for the solution! This is my own attempt, after rewriting my initial, not very efficient, implementation. I thought someone might find it useful:
function [majorityPts] = MajorityPointSelection(Mat, numMajority)
result = vertcat(Mat{:});
allUniq = unique(result(:,1:2),'rows');
numUniq = size(allUniq,1);
allUniq = [allUniq zeros(numUniq,1); zeros(size(result,1)-numUniq, 3)];
for i = 1:numUniq
sumNumRow = sum(result(:,1:2) == allUniq(i,1:2),1);
allUniq(i,3) = sumNumRow(1);
end
allUniq(numUniq+1:end,:) = [];
majorityPts = allUniq(allUniq(:,3)>=numMajority,1:2);
end
Here Mat is a cell that contains all of the arrays that I want to compare in order to find the rows that appear in at least numMajority of them, where in my case numMajority = 3. Basically, I first dump all of the arrays in one big matrix (result), and then find the unique rows of this matrix. Finally, I count the number of each unique row and return the points that appear in the majority number of arrays as majorityPts.
I am very new to MatLab and have the following problem: I have 2 arrays with a lot of integers, and I would like to be able to assign any given data point from one array to another. Example:
array1 = [1, 2, 3]
array2 = [2, 4, 6]
So if I have a data from array1, in this case, I would be able to say array1*2 = array2. There are different ways to solve this, and I have two arrays with about 100k elements each. I need to divide the data into smaller segments and then create an average for each, so that I may be able to derive that for array1*X ~ array2. I need a good estimation, the example above just doesnt do it any justice. Thanks for the help
From what I understand you want to estimate X in your formula:
array1*X = array2
If you devide you get the estimate for each value, than take the mean to have an estimator of X
mean(double(array2)./double(array1))
You worry about the 100k values, 200k values in total. This is not big for Matlab. Concider that each value takes up 8 bytes. 1600kB is not much for a computer.
You could also fit it with a simple linear regression model
sum(array1.*array2) / sum(array1.^2)
Let's try again. So you have 2x 100k points that have a relation y = b*x.
You want to find b for different segments of the 100k points.
x = randi([1 2^15-1],1,1E5,'uint16'); %demo data
y = x.*2;
The two methods I gave before will yield 2:
x=double(x);y=double(y);
mean(y./x)
sum(x.*y) / sum(x.^2)
If you want to segment you can first cut the data in smaller parts
segment=1000; %nr datapoints / segment
N = length(x)/segment; %nr of segments
L = floor(rem(N,1)*segment); %nr of datapoints in last segment
N = floor(N);
xc=mat2cell(x,1,[repmat(segment,[1,N]),L]);
yc=mat2cell(y,1,[repmat(segment,[1,N]),L]);
if L==0,xc(end)=[];yc(end)=[];end
Now you can loop over xc and get the mean value
for ct = 1:length(xc)
x = xc{ct};y=yc{ct};
m(ct) = mean(y./x);
m2(ct) = sum(x.*y) / sum(x.^2);
end
I have 5-dimensional array of numbers. The goal is to find maximum values along 5-th dimension and their coordinates. I use
[x,y] = max(A,[],5);
Ideally I expect that x == A(y), however this does not appear to happen. I need an idea of how to translate y to an array of coordinates z such that x == A(z). Using find + loops is costly in my case, since matrices are huge.
Suppose your matrix A has dimension of (m,n,o). Now you have the indices of maximum entries along the 3rd dimension in y and the corresponding maximum values in x. You can access the maximum values by the following code-
z = (1:m*n)' + (y(:)-1)*(m*n); % linear index of these locations in full array
final_matrix = reshape(A(z),m,n);
It can be easily extended to 5 dimensional matrices.
Try this code for 5-dimensional-
[x,y] = max(A,[], 5);
z = (1:m*n*o*p)' + (y(:)-1)*(m*n*o*p);
final_matrix = reshape(A(z),m,n,o,p);
s = size(A);
[v,ii] = max(reshape(A,[],s(3)));
[i1 j1 ] = ind2sub(s(1:2),ii);
out = [v;i1;j1;1:s(3)]';
Consider that I have a vector/array such that it looks as follows:
each part is a sub array of some size fixed and known size (that can only be accessed through indexing, i.e. its not a tensor nor a higher order array). So for example:
x1 = x(1:d);
if d is the size of each sub array. The size of each sub array is the same but it might vary depending on the current x we are considering. However, we do know n (the number of sub arrays) and d (the size of all of the sub arrays).
I know there is usually really strange but useful tricks in matlab to do things more optimized. Is there a way to extract those using maybe indexing and and make a matrix where the rows (or columns) are those parts? as in:
X = [x_1, ..., x_n]
the caveat is that n is a variable and we don't know aprior what it is. We can find what n is, but its not fixed.
I want to minimize the amount of for loops I actually write in matlab to hope its faster...just to add some more context.
First I would consider simple reshaping to keep the output as a simple double matrix
x = (1:15).' %'
d = 3;
out = reshape(x,d,[])
and further on just use indexing to access the columns out(:,idx);
There is no need to know n in advance, as reshape is calculating it based on d and the number of elements in x.
out =
1 4 7 10 13
2 5 8 11 14
3 6 9 12 15
If you'd insist on something like cell arrays, use accumarray with ceil to get the subs:
out = accumarray( ceil( (1:numel(x))/d ).', x(:), [], #(x) {x})
Let's say we have an array x. We can find the maximum value of this array as follows:
maximum = max(x);
If I have two arrays, let's say x and y, I can find the array that contains the maximum value by using the command
maximum_array = max(x, y);
Let's say that this array is y. Then, I can find the maximum value by using the max command with argument y, as before with x:
maximum_value = max(y);
This two-step procedure could be performed with the following compact, one-liner command:
maximum_value = max(max(x, y));
But what happens when we have more than 2 arrays? As far as I know, the max function does not allow to compare more than two arrays. Therefore, I have to use max for pairs of arrays, and then find the max among the intermediate results (which involves also the use of additional variables). Of course, if I have, let's say, 50 arrays, this would be - and it really is - a tedius process.
Is there a more efficient approach?
Approach #1
Concatenate column vector versions of them along dim-2 with cat and then use maximium values with max along dim-2 to get the max.
Thus, assuming x, y and z to be the input arrays, do something like this -
%// Reshape all arrays to column vectors with (:) and then use cat
M = cat(2,x(:),y(:),z(:))
%// Use max along dim-2 with `max(..,[],2)` to get column vector
%// version and then reshape back to the shape of input arrays
max_array = reshape(max(M,[],2),size(x))
Approach #2
You can use ndims to find the number of dimensions in the input arrays and then concatenate along the dimension that is plus 1 of that dimension and finally find max along it to get the maximum values array. This would avoid all of that reshaping back and forth and thus could be more efficient and a more compact code as well -
ndimsp1 = ndims(x)+1 %// no. of dimensions plus 1
maxarr = max(cat(ndimsp1,x,y,z),[],ndimsp1) %// concatenate and find max
I think the easiest approach for a small set of arrays is to column-ify and concatenate:
maxValue = max([x(:);y(:)]);
For a large number of arrays in some data structure (e.g. a cell array or a struct), I simple loop would be best:
maxValue = max(cellOfMats{1}(:));
for k = 2:length(cellOfMats)
maxValue = max([maxValue;cellOfMats{k}(:)]);
end
For the pathological case of a large number of separate arrays with differing names, I say "don't do that" and put them in a data structure or use eval with a loop.