I need to do the following for each of elements of a matrix of size mXn:
1. flip a coin with a 0.3 probability of success.
2. if its a success set the element to zero.
3. else move to the next element.
I used the following code, but it does not give any output and produces NaN, C is the matrix of size mXn:
index = (rand(size(C)<=0.3));
one_index = find(index ==1);
C(one_index) = 0;
The problem is this statement
index = (rand(size(C)<=0.3));
You've messed up the parentheses so you're trying to compare if size(C) <= 0.3. This returns [0 0], causing rand to create an empty matrix.
Also, the call to find is unnecessary.
C = magic(4);
index = rand(size(C)) <= 0.3;
C(index) = 0
C =
16 2 3 13
0 11 10 8
9 7 6 0
4 0 15 1
Related
I have a vector M containing single elements and repeats. I want to delete all the single elements. Turning something like [1 1 2 3 4 5 4 4 5] to [1 1 4 5 4 4 5].
I thought I'd try to get the count of each element then use the index to delete what I don't need, something like this:
uniq = unique(M);
list = [uniq histc(M,uniq)];
Though I'm stuck here and not sure how to go forward. Can anyone help?
Here is a solution using unique, histcounts and ismember:
tmp=unique(M) ; %finding unique elements of M
%Now keeping only those elements in tmp which appear only once in M
tmp = tmp(histcounts(M,[tmp tmp(end)])==1); %Thanks to rahnema for his insight on this
[~,ind] = ismember(tmp,M); %finding the indexes of these elements in M
M(ind)=[];
histcounts was introduced in R2014b. For earlier versions, hist can be used by replacing that line with this:
tmp=tmp(hist(M,tmp)==1);
You can get the result with the following code:
A = [a.', ones(length(a),1)];
[C,~,ic] = unique(A(:,1));
result = [C, accumarray(ic,A(:,2))];
a = A(~ismember(A(:,1),result(result(:,2) == 1))).';
The idea is, add ones to the second column of a', then accumarray base on the first column (elements of a). After that, found the elements in first column which have accum sum in the second column. Therefore, these elements repeated once in a. Finally, removing them from the first column of A.
Here is a cheaper alternative:
[s ii] = sort(a);
x = [false s(2:end)==s(1:end-1)]
y = [x(2:end)|x(1:end-1) x(end)]
z(ii) = y;
result = a(z);
Assuming the input is
a =
1 1 8 8 3 1 4 5 4 6 4 5
we sort the list s and get index of the sorted list ii
s=
1 1 1 3 4 4 4 5 5 6 8 8
we can find index of repeated elements and for it we check if an element is equal to the previous element
x =
0 1 1 0 0 1 1 0 1 0 0 1
however in x the first elements of each block is omitted to find it we can apply [or] between each element with the previous element
y =
1 1 1 0 1 1 1 1 1 0 1 1
we now have sorted logical index of repeated elements. It should be reordered to its original order. For it we use index of sorted elements ii :
z =
1 1 1 1 0 1 1 1 1 0 1 1
finally use z to extract only the repeated elements.
result =
1 1 8 8 1 4 5 4 4 5
Here is a result of a test in Octave* for the following input:
a = randi([1 100000],1,10000000);
-------HIST--------
Elapsed time is 5.38654 seconds.
----ACCUMARRAY------
Elapsed time is 2.62602 seconds.
-------SORT--------
Elapsed time is 1.83391 seconds.
-------LOOP--------
Doesn't complete in 15 seconds.
*Since in Octave histcounts hasn't been implemented so instead of histcounts I used hist.
You can test it Online
X = [1 1 2 3 4 5 4 4 5];
Y = X;
A = unique(X);
for i = 1:length(A)
idx = find(X==A(i));
if length(idx) == 1
Y(idx) = NaN;
end
end
Y(isnan(Y)) = [];
Then, Y would be [1 1 4 5 4 4 5]. It detects all single elements, and makes them as NaN, and then remove all NaN elements from the vector.
I would like to write a "syntactical sugar" Octave or Matlab zero-padding function, to which the user sends an n-dimensional object and a vector of <= n entries. The vector contains new, equal or larger dimensions for the object, and the object is zero-padded to match these dimensions. Any dimensions not specified are left alone. One expected use is, given for example a 5d block X of 3d medical image volumes, I can call
y = simplepad(X, [128 128 128]);
and thus pad the first three dimensions to a power of two for wavelet analysis (in fact I use a separate function nextpwr2 to find these dimensions) while leaving the others.
I have racked my brains on how to write this method avoiding the dreaded eval, but cannot thus far find a way. Can anyone suggest a solution? Here is more or less what I have:
function y = simplepad(x, pad)
szx = size(x);
n_pad = numel(pad);
szy = [pad szx(n_pad+1:end)];
y = zeros(szy);
indices_string = '(';
for n = 1:numel(szx)
indices_string = [indices_string, '1:', num2str(szx(n))];
if n < numel(szx)
indices_string = [indices_string, ','];
else
indices_string = [indices_string, ')'];
end
end
command = ['y',indices_string,'=x;'];
eval(command);
end
Here's a solution that should handle all the little corner cases:
function A = simplepad(A, pad)
% Add singleton dimensions (i.e. ones) to the ends of the old size of A
% or pad as needed so they can be compared directly to one another:
oldSize = size(A);
dimChange = numel(pad)-numel(oldSize);
oldSize = [oldSize ones(1, dimChange)];
pad = [pad ones(1, -dimChange)];
% If all of the sizes in pad are less than or equal to the sizes in
% oldSize, there is no padding done:
if all(pad <= oldSize)
return
end
% Use implicit zero expansion to pad:
pad = num2cell(pad);
A(pad{:}) = 0;
end
And a few test cases:
>> M = magic(3)
M =
8 1 6
3 5 7
4 9 2
>> simplepad(M, [1 1]) % No change, since the all values are smaller
ans =
8 1 6
3 5 7
4 9 2
>> simplepad(M, [1 4]) % Ignore the 1, pad the rows
ans =
8 1 6 0
3 5 7 0
4 9 2 0
>> simplepad(M, [4 4]) % Pad rows and columns
ans =
8 1 6 0
3 5 7 0
4 9 2 0
0 0 0 0
>> simplepad(M, [4 4 2]) % Pad rows and columns and add a third dimension
ans(:,:,1) =
8 1 6 0
3 5 7 0
4 9 2 0
0 0 0 0
ans(:,:,2) =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
As I understand, you want just pass the some dynamic arguments to function.
You can do this by converting these arguments to cell and call your function with passing cell content. So, your function will look like:
function y = simplepad(x, pad)
szx = size(x);
n_pad = numel(pad);
szy = [pad szx(n_pad+1:end)];
y = x;
szyc = num2cell(szy);
y(szyc{:}) = 0; % warning: assume x array only grows
end
I want to create a matrix with all the possible combinations of 10 numbers between 0 and 100, with intervals of 5, that its sum be equal to 100. I mean something like this:
(0 0 0 0 0 0 0 0 0 10 90; 10 10 10 10 10 10 10 10 20 0;...)
I use "allcomb.m" to create something like all the possible numbers that are between 0 and 100, with intervals of 5. However, this matrix is so big, and that implies that Matlab doesn't create it. I was thinking that, if I have that matrix, I could reduce it using a condition but this is impossible because I never get the matrix.
So, the question is how I can modify the allcomb's code with the condition in the same code or maybe, and better, another way to create the matrix that I purpose.
Be warned that even the result matrix is very large - to be precise, it has 10,015,005 rows and ten columns, and (if stored as a double) takes up about 1GB of space. On my machine it takes about ten minutes to compute. Nevertheless, it is computable, and the following function computes it.
function w = allconstrainedcombinations(n,k)
if n == 1
w = k;
else
t = nchoosek(n+k-1,k); # Total number of rows
w = zeros(t,n); # Pre-allocate
r = 1; # Current row
for v = 0:k
u = allconstrainedcombinations(n-1,k-v);
m = size(u,1);
w(r:r+m-1,1) = v;
w(r:r+m-1,2:end) = u;
r = r + m;
end
end
end
To get the result you want, you should call
>> x = allconstrainedcombinations(10,20) * 5;
Here's the result for a small example:
>> allconstrainedcombinations(3,2)
ans =
0 0 2
0 1 1
0 2 0
1 0 1
1 1 0
2 0 0
I want to run fast Matlab algorithms over Matrices by ignoring zero-elements.
In the past I just worked with a very slow double-for-loop e.g.
for i = 1 : size(x,1)
for j = 1 : size(x,2)
if x(i,j) ~= 0
... do something with x(i,j)
end
end
end
But how can I make the matrix operation on the whole matrix x?
E.g. how can I run
x(i,j) = log(x(i,j)) if x>0 else 0 <-- pseudo code
in Matlab on the whole matrix without for loops?
Finally I want to rewrite lines like
result = sum(sum((V.*log(V./(W*H))) - V + W*H));
with ignoring zeros.
I just need to understand the concept.
In case of need I could also use NaN instead of zero, but I didn't find e.g. the function
nanlog()
x~=0 returns you the indices of the locations not equal to zero. Then, you can use them to index corresponding locations of x such as follows:
>> x = [1 0 2 3; 0 4 0 5]
x =
1 0 2 3
0 4 0 5
>> mean(x(:)) %#mean of all elements
ans =
1.8750
>> mean(x(x~=0)) %#mean of nonzero elements
ans =
3
>> x(x~=0) = x(x~=0) + 1
x =
2 0 3 4
0 5 0 6
You can use NaN as a temporary and make use of the fact that log(NaN) = NaN, like so:
x(x==0) = NaN;
y = log(x);
y(isnan(y)) = 0;
alternatively, you can use logical indexing:
x(x~=0) = log(x(x~=0));
or, if you want to preserve x,
y = x;
y(y~=0) = log(y(y~=0));
For the example you provide, you can just do
result = nansum(nansum((V.*log(V./(W*H))) - V + W*H));
assuming that V == 0 is the problem.
I'm looking for an elegant solution to this very simple problem in MATLAB. Suppose I have a matrix
>> M = magic(5)
M =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
and a logical variable of the form
I =
0 0 0 0 0
0 1 1 0 0
0 1 1 0 0
0 0 0 0 0
0 0 0 0 0
If I try to retrieve the elements of M associated to 1 values in I, I get a column vector
>> M(I)
ans =
5
6
7
13
What would be the simplest way to obtain the matrix [5 7 ; 6 13] from this logical indexing?
If I know the shape of the non-zero elements of I, I can use a reshape after the indexing, but that's not a general case.
Also, I'm aware that the default behavior for this type of indexing in MATLAB enforces consistency with respect to the case in which non-zero values in I do not form a matrix, but I wonder if there is a simple solution for this particular case.
This is a one way to do this. It is assumed that all rows of I have same number of ones. It is also assumed that all columns of I have same number have ones, because Submatrix must be rectangular.
%# Define the example data.
M = magic(5);
I = zeros(5);
I(2:3, 2:3) = 1;
%# Create the Submatrix.
Submatrix = reshape(M(find(I)), max(sum(I)), max(sum(I')));
Here is a very simple solution:
T = I(any(I'),any(I));
T(:) = M(I);
M = magic(5);
I = [ ... ];
ind = find(I); %# find indices of ones in I
[y1, x1] = ind2sub(size(M), ind(1)); %# get top-left position
[y2, x2] = ind2sub(size(M), ind(end)); %# get bottom-right position
O = M(y1:y2, x1:x2); %# copy submatrix