I have an array A size of 16X16 and I want to add first 3 rows out of 16 in A. What is the most efficient solution in MATLAB?
I tried this code but this is not efficient because I want to extend it for large arrays:
filename = 'n1.txt';
B = importdata(filename);
i = 1;
D = B(i,:)+ B(i+1,:)+ B(i+2,:);
For example, if I want to extend this for an array of size 256x256 and I want to extract 100 rows and add them, how I will do this?
A(1:3,:);%// first three rows.
This uses the standard indices of matrix notation. Check Luis's answer I linked for the full explanation on indices in all forms. For summing things:
B = A(1:100,:);%// first 100 rows
C = sum(B,1);%// sum per column
D = sum(B,2);%// sum per row
E = sum(B(:));%// sum all elements, rows and columns, to a single scalar
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.
Given a vector X of discrete positive integers with size 160*1, and a table Tb1 in size 40*200, that contains a list of indices to be deleted from X Each column from the 200 columns in Tb1 points to 40 elements to be deleted from original X.
I create a new matrix of the remaining 120*200 elements by using a for loop with 200 iterations, that at round i deletes 40 elements from a copy of the original X according to the indices listed in Tb1(:,i), but it takes too much time and memory.
How can I get the result without using loops and with a minimum number of operations?
Here are different methods:
Method1:
idx = ~hist(tbl, 1:160);
[f,~]=find(idx);
result1 = reshape(M(f),120,200);
Method2:
idx = ~hist(tbl, 1:160);
M2=repmat(M,200,1);
result2 = reshape(M2(idx),120,200);
Method 3 & 4:
% idx can be generated using accumarray
idx = ~accumarray([tbl(:) reshape(repmat(1:200,40,1),[],1)],true,[160,200],#any);
%... use method 1 and 2
Method5:
M5=repmat(M,200,1);
M5(bsxfun(#plus,tbl,0:160:160*199))=[];
result5 = reshape(M5,120,200);
Assuming that M is an array of integers and tbl is the table of indices.
It can be tested with the following data:
M = rand(160,1);
[~,tbl] = sort(rand(160,200));
tbl = tbl(1:40,:);
However it is more efficient if you generate indices of elements to be remained instead of indices of elements to be removed.
I'm working in Matlab.
I have a two-dimensional matrix with two columns. Lets consider elements in the first column as labels. Labels may be repeated.
How to multiply all elements in the second column for every label?
Example:
matrix = [1,3,3,1,5; 2,3,7,8,3]'
I need to get:
a = [1,3,5; 16,21,3]'
Can you help me with doing it without for-while cycles?
I would use accumarray. The preprocessing with unique assigns integer indices 1:n to the values in the first row, which allow accumarray to work without creating unnecessary bins for 2 and 4. It also enables the support for negative numbers and floats.
[ulable,~,uindex]=unique(matrix(:,1))
r=accumarray(uindex,matrix(:,2),[],#prod)
r=[ulable,r]
/You can also use splitapply:
[ulable,~,uindex]=unique(matrix(:,1))
r=splitapply(#prod,matrix(:,2),uindex)
r=[ulable,r]
You can do it without loops using accumarray and the prod function:
clear
clc
matrix = [1,3,3,1,5; 2,3,7,8,3]';
A = unique(matrix,'rows');
group = A(:,1);
data = A(:,2);
indices = [group ones(size(group))];
prods = accumarray(indices, data,[],#prod); %// As mentionned by #Daniel. My previous answer had a function handle but there is no need for that here since prod is already defined in Matlab.
a = nonzeros(prods)
Out = [unique(group) a]
Out =
1 16
3 21
5 3
Check Lauren blog's post here, accumarray is quite interesting and powerful!
Try something like this, I'm sure it can be improved...
unValues = unique(matrix(:,1));
bb = ones(size(unValues));
for ii = 1:length(unValues)
bb(ii) = bb(ii)*prod(matrix(matrix(:, 1) == unValues(ii), 2));
end
a = [unValues bb];
I have three column vectors, then I want to creat matrix from this column victors
A1(:);
A2(:);
A3(:)
each column vectors has 25 element then the new matrix C will be a matrix with 3x25
I want to make A1(:) the first column of matrix c
A2(:) second column
A3(:) third column
Use cat to concatenate along dimension 1 or 2 depending on how you input those three vectors.
Thus, you can use -
C = cat(2,A1(:),A2(:),A3(:)).'
Or
C = cat(1,A1(:).',A2(:).',A3(:).')
Of course, you can skip (:)'s, if you know that all those are column vectors.
The above two approaches assumes that you intend to get an output of size 3 x N, where is N is the number of elements in the column vectors. If you were looking to get an output of size N x 3 , i.e. where each column is formed from the elements of column vectors A1, A2 and so on, just drop the transpose from the first of the two approaches mentioned above. Thus, use this -
C = cat(2,A1(:),A2(:),A3(:))
I need to turn a large array into a matrix in the following way: to take the first m entries of the array and make that the 1st row of the matrix.
For example: if I had an array that was 100 entries long, the corresponding matrix would be 10 rows and each row would be 10 entries of the array with the order preserved.
I've tried the following code:
rows = 10
row_length = 10
a = randi(1,100);
x = zeros(rows,row_length)
for i=1:rows
x(i) = a(i:i+row_length)
end
but with no luck. I'm stuck on how to slide the window along by row_length so that i will start from row_length+1 in the second (and subsequent) iterations of the loop.
The best way to do it is to use Matlab's reshape function:
reshape(a,row_length,[]).'
It will reshape by first assigning down the columns which is why I transpose at the end (i.e. .')
However just for the sake of your learning, this is how you could have done it your way:
rows = 10
row_length = 10
a = rand(1,100)
x = zeros(rows,row_length)
for i=1:row_length:rows*row_length %// use two colons here, the number between them is the step size
x(i:i+row_length-1) = a(i:i+row_length-1) %// You need to assign to 10 elements on the left hand side as well!
end