Matlab sums and integers - matlab

Thank you for any help in advance. I have a large matrix: 1,000,000 rows and 10 columns. I would like to sum each row and create a new matrix with only the rows that sum to integers. I've tried this so far and manipulated it in many ways, but I'm stuck. How can I do this?
for k = 1:1000000
x = sum(A(k,:)) %A is my large matrix
if x-round(x,0)==0
y = [y;x]% y is my new matrix
end
end

Rather than using a for loop and continuously expanding y which is going to be extremely slow for large x arrays, you can use the second input of sum to compute the sum for each row, and then you can determine which rows sum to an integer by comparing the rounded and original versions using a very small epsilon (the proper way to compare floating-point numbers).
% Sum each row and divide by 3
row_sums = sum(x, 2) / 3;
% Determine which of the row-wise sums are integers
sum_is_integer = abs(round(row_sums) - row_sums) < eps;
% If you want the sums that were integers
y = row_sums(sum_is_integer);
% If you want a sub-matrix containing only the rows where the sums were an integer
z = x(sum_is_integer, :);

Related

Divide a matrix and its corresponding vector into submatrices and subvectors in MATLAB

I have two matrices X (122 x 125973) and Y (1 x 125973). I want to split in the same way X and Y into smaller matrices and vectors of 122 x 1024 (column division) in Matlab.
I have tried several methods (mat2cell, loops, etc), but I think I am missing the syntax. Any help ?
Note: 125973 can't be divided by 1024, so the last matrix (and vector) will the have the size of (122 x 21) (and (1 x 21) respectively). Thank you for your help!
Since your sub-matrices do not have equal size, you cannot put them in a 3D array (without NaN or zero padding). So you can use a cell. To do this with mat2cell you have to specify how many rows of the original matrix should be put in each individual entry of the cell:
X = rand(122,125973);
Y = rand(1,125973);
% your number of rows per 'block'
n = 1024;
% the number of cols per cell entry:
colDist = [repelem(n, floor(size(X,2)/n)) rem(size(X,2),n)];
Xcell = mat2cell(X, size(X,1), colDist);
Ycell = mat2cell(Y, size(Y,1), colDist);
Here repelem(n, floor(size(X,2)/n)) repeats n for the number of times n fits in the number of columns of X. Then I append the remainder for the number of columns at the end (rem(size(X,2),n)) of this division to this row vector colDist.
When calling mat2cell (mat2cell(X, rowDist, colDist)) the second argument rowDist should then contain the number of rows per cell entry, which for each cell entry will be equal to the number of rows in X or Y.
Alternatively, you can use a loop to divide the matrix and vector in sub-matrices and put them in the appropriate cell.
Xcell = cell(ceil(size(X,2)/n),1);
Ycell = cell(ceil(size(X,2)/n),1);
% put in the blocks of n rows
for k = 1:floor(size(X,2)/n)
indices = n*(k-1)+1:n*k;
Xcell{k} = X(:,indices);
Ycell{k} = Y(:,indices);
end
% and the remainder:
Xcell{end} = X(:, indices(end)+1:end);
Ycell{end} = Y(:, indices(end)+1:end);

How to sum 3d Matrix row by interval in Matlab?

I have a 36x256x2232 3d matrix in Matlab created by M = ones(36,256,2232) and I want to reduce the size of the matrix by sum rows by interval 3. The result matrix should be 12x256x2232 and each cell should have the value 3.
I tried using reshape and sum function but I get 1x256x2232 matrix.
How can I do this without using the for-loop ?
This should do it:
M = ones(36,256,2232)
reduced = reshape(sum(reshape(M, 3,[], 256,2232), 1),[], 256, 2232);
reshape makes a 4d matrix with the given intervals
sum reduce it
second reshape transform it to 3d again
you can use also squeeze, which removes singleton dimensions:
reduced = squeeze(sum(reshape(M, 3,[], 256,2232), 1));
You can use the new-ish splitapply function (which is similar to accumarray but can handle data with multiple dimensions). This approach works even if the number of rows is not a multiple of the group size:
M = ones(4,5,2); % example data
n = 3; % group size
result = splitapply(#(x)sum(x,1), M, floor((0:size(M,1)-1).'/n)+1);

Random numbers using rand() in matlab

I am using Matlab function round(rand(256)) to create a square matrix of size 256x256 with random distribution of 0s and 1s.
What I specifically want to do is that I want to somehow specify number of 1s that rand() (or any other relevant function for that matter) to generate and distribute throughout the matrix randomly
Magdrop’s answer is the most straight-forward method, it computes the percentile of the random values to determine the threshold.
Another two options involve randperm:
Randomly permute all indices into the matrix, then threshold:
sz = [256,256]; % matrix size
n = 256; % number of zeros
M = randperm(prod(sz)) <= n;
M = reshape(M,sz);
Randomly permute indices and select n as the locations of the ones:
indx = randperm(prod(sz),n);
M = zeros(sz);
M(indx) = 1;
You could also generate the random value the usual way, but before you round them, sort them as a vector. The number of 1s will the index in the sorted vector you want to cut for 1s or 0s. For example, let say we want 50 1s:
matrix = rand(256,256);
vec = sort(reshape(matrix,[],1));
thresh = vec(50);
matrix(matrix <= thresh) = 1;
matrix(matrix > thresh) = 0;
You could use the randi function to determine the locations of where to insert the ones, and then place those ones into your matrix. For example for n ones:
matrix = zeros(256,256);
onesIndices = randi([0 256*256],1,n);
matrix(onesIndices) = 1;
One problem with this approach is that randi can generate repeat values, though for this example, where the size of the matrix is large and the number of ones is low, this is pretty unlikely. You could test if this is the case and "reroll:" so if sum(sum(matrix)) is less than n you know you had a repeat value.
Edit: a better approach is to use randperm instead of randi and only take the first n elements. This should prevent there from being repeats and having to re-roll.

Vector and matrix comparison in MATLAB

I have vector with 5 numbers in it, and a matrix of size 6000x20, so every row has 20 numbers. I want to count how many of the 6000 rows contain all values from the vector.
As the vector is a part of a matrix which has 80'000'000 rows, each containing unique combinations, I want a fast solution (which doesn't take more than 2 days).
Thanks
With the sizes you have, a bsxfun-based approach that builds an intermediate 6000x20x5 3D-array is affordable:
v = randi(9,1,5); %// example vector
M = randi(9,6000,20); %// example matrix
t = bsxfun(#eq, M, reshape(v,1,1,[]));
result = sum(all(any(t,2),3));

How to select values with the higher occurences from several matrices having the same size in matlab?

I would like to have a program that makes the following actions:
Read several matrices having the same size (1126x1440 double)
Select the most occuring value in each cell (same i,j of the matrices)
write this value in an output matrix having the same size 1126x1440 in the corresponding i,j position, so that this output matrix will have in each cell the most occurent value from the same position of all the input matrices.
Building on #angainor 's answer, I think there is a simpler method using the mode function.
nmatrices - number of matrices
n, m - dimensions of a single matrix
maxval - maximum value of an entry (99)
First organize data into a 3-D matrix with dimensions [n X m X nmatrices]. As an example, we can just generate the following random data in a 3-D form:
CC = round(rand(n, m, nmatrices)*maxval);
and then the computation of the most frequent values is one line:
B = mode(CC,3); %compute the mode along the 3rd dimension
Here is the code you need. I have introduced a number of constants:
nmatrices - number of matrices
n, m - dimensions of a single matrix
maxval - maximum value of an entry (99)
I first generate example matrices with rand. Matrices are changed to vectors and concatenated in the CC matrix. Hence, the dimensions of CC are [m*n, nmatrices]. Every row of CC holds individual (i,j) values for all matrices - those you want to analyze.
CC = [];
% concatenate all matrices into CC
for i=1:nmatrices
% generate some example matrices
% A = round(rand(m, n)*maxval);
A = eval(['neurone' num2str(i)]);
% flatten matrix to a vector, concatenate vectors
CC = [CC A(:)];
end
Now we do the real work. I have to transpose CC, because matlab works on column-based matrices, so I want to analyze individual columns of CC, not rows. Next, using histc I find the most frequently occuring values in every column of CC, i.e. in (i,j) entries of all matrices. histc counts the values that fall into given bins (in your case - 1:maxval) in every column of CC.
% CC is of dimension [nmatrices, m*n]
% transpose it for better histc and sort performance
CC = CC';
% count values from 1 to maxval in every column of CC
counts = histc(CC, 1:maxval);
counts have dimensions [maxval, m*n] - for every (i,j) of your original matrices you know the number of times a given value from 1:maxval is represented. The last thing to do now is to sort the counts and find out, which is the most frequently occuring one. I do not need the sorted counts, I need the permutation that will tell me, which entry from counts has the highest value. That is exactly what you want to find out.
% sort the counts. Last row of the permutation will tell us,
% which entry is most frequently found in columns of CC
[~,perm] = sort(counts);
% the result is a reshaped last row of the permutation
B = reshape(perm(end,:)', m, n);
B is what you want.