Is there a general uniques counting function? - function

By general, I mean it can count the different elements in the input given it is either a list of numbers (or other atoms), a list of vectors or a list of matrices.
Example: given a list of row vectors of length 3:
x = [1 1 1; 1 0 1; 0 1 1; 1 0 1; 1 1 1; 1 0 1];
the expected outcome should be:
[1 1 1] --> 2
[1 0 1] --> 3
[0 1 1] --> 1
returned in e.g. two lists. I know about the count_uniques function, but it deals with non-array inputs only, as far as I know.

You can use unique. If the input is an array use unique(X,'rows').
If you want a universal function you can do:
function varargout=universal_unique(X);
if(size(X,2)==1)
[varargout{:}]=unique(X);
else
[varargout{:}]=unique(X,'rows');
end
end

Related

Applying 'vector' of functions on a Matlab matrix

Let's say I've got a matrix with n columns, and I've got n different functions.
Is it possible to apply i-th function per each element in i-th column efficiently, that is without using loop?
For example for the following variables:
funs = #(x) [x, cos(x), x.^2]
A = [1 0 1
2 0 2
3 0 3
4 0 4] ;
I would like to obtain the following result:
B = [1 1 1
2 1 4
3 1 9
4 1 16] ;
without looping through columns...

Octave element wise comparisons [duplicate]

let us consider following code for impulse function
function y=impulse_function(n);
y=0;
if n==0
y=1;
end
end
this code
>> n=-2:2;
>> i=1:length(n);
>> f(i)=impulse_function(n(i));
>>
returns result
f
f =
0 0 0 0 0
while this code
>> n=-2:2;
>> for i=1:length(n);
f(i)=impulse_function(n(i));
end
>> f
f =
0 0 1 0 0
in both case i is 1 2 3 4 5,what is different?
Your function is not defined to handle vector input.
Modify your impluse function as follows:
function y=impulse_function(n)
[a b]=size(n);
y=zeros(a,b);
y(n==0)=1;
end
In your definition of impulse_function, whole array is compared to zero and return value is only a single number instead of a vector.
In the first case you are comparing an array to the value 0. This will give the result [0 0 1 0 0], which is not a simple true or false. So the statement y = 0; will not get executed and f will be [0 0 0 0 0] as shown.
In the second you are iterating through the array value by value and passing it to the function. Since the array contains the value 0, then you will get 1 back from the function in the print out of f (or [0 0 1 0 0], which is an impulse).
You'll need to modify your function to take array inputs.
Perhaps this example will clarify the issue further:
cond = 0;
if cond == 0
disp(cond) % This will print 0 since 0 == 0
end
cond = 1;
if cond == 0
disp(cond) % This won't print since since 1 ~= 0 (not equal)
end
cond = [-2 -1 0 1 2];
if cond == 0
disp(cond) % This won't print since since [-2 -1 0 1 2] ~= 0 (not equal)
end
You could define your impulse function simply as this one -
impulse_function = #(n) (1:numel(n)).*n==0
Sample run -
>> n = -6:4
n =
-6 -5 -4 -3 -2 -1 0 1 2 3 4
>> out = impulse_function(n)
out =
0 0 0 0 0 0 1 0 0 0 0
Plot code -
plot(n,out,'o') %// data points
hold on
line([0 0],[1 0]) %// impulse point
Plot result -
You can write an even simpler function:
function y=impulse_function(n);
y = n==0;
Note that this will return y as a type logical array but that should not affect later numerical computations.

round to the nearest even number with array of numbers

My function and rounding to nearest even number
function y = rndeven(x)
if x<=1
y=2;
else
y = 2*floor(x);
end
endfunction
When I run it I get:
cc=[0:3]'
both=[cc,rndeven(cc)]
0 0
1 2
2 4
3 6
What I'm trying to get as the Result:
0 2
1 2
2 2
3 4
You can use the modulo 2 to find whether a number is even. If it isn't this will return 1, so just add 1 to this number to find the nearest (larger) even number:
function y = rndeven(x)
x = floor(x);
x(x <= 1) = 2;
y = mod(x,2)+x;
end
This works for any array, order of elements does not matter.
You could also check if it is dividable by 2 if you don't want to use the mod function. The pseudo code would be something like this:
while(x % 2 != 0) x = x + 1
return x

Octave: Replacing element of matix/vector with a vector

I am trying to turn each element in a matrix from a value from 1 to 10 into a 10x1 zeros matrix where the element of the zeros matrix corresponding to the value of the original element is equal to 1.
Here is the code:
function q = convert
% Convert y matrix values to 10x1 vector
load('y.mat');
ZERO = zeros(10,1);
% Set 10x1 Matrix of zeros
for i = 1:length(y)
ZERO(y(i)) = 1; % Set yth element of ZERO to 1
y(i) = ZERO; % Set ith element of y equal to new zero
ZERO = zeros(10,1); % Re-establish zero
endfor
When I run it I get the error A(I) = X: X must have the same size as I. Where the matrix I am trying to input does not agree with the size of element of matrix y. Can I get around this?
Sample input:
y = [1; 2; 3; 4; 5]
Sample output:
y = [[1;0;0;0;0;0;0;0;0;0],
[0;1;0;0;0;0;0;0;0;0],
[0;0;1;0;0;0;0;0;0;0],
[0;0;0;0;1;0;0;0;0;0],
[0;0;0;0;0;1;0;0;0;0]]
I'm going to make a couple of assumptions:
You want the return value to be q as in the function signature, and
You want the output in your sample case to be a 10x5 matrix like so:
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
Fixing the loop
The problem that gives the error is that you're assigning a 10x1 vector ZERO to a single (scalar) element of the 5x1 vector y:
y(i) = ZERO;
A vector doesn't fit in a scalar. But even if you change this to assign ZERO to a column of y, it doesn't fit because the lengths of the columns are different. That's not what you want to do anyway, because if it had worked, you would have just wiped out the values in y. So let's set the values in the columns of the output array q. (Changes are marked with <== in the comments.)
function q = convert
% Convert y matrix values to 10xn matrix
%load('y.mat');
y = [1; 2; 3; 4; 5]; % <== replace load temporarily
% Set 10x1 Matrix of zeros
ZERO = zeros(10,1);
% Preallocate output array
q = zeros(10, length(y)); % <== preallocate for speed
for i = 1:length(y)
ZERO(y(i)) = 1; % Set yth element of ZERO to 1
q(:,i) = ZERO; % <== Set ith *column* of *q* equal to new zero
ZERO = zeros(10,1); % Re-establish zero
endfor
Improving the loop
This will work, but if you preallocate q, you've already got the correct number of ZERO vectors, so why not just set the values directly?
function q = convert
% Convert y matrix values to 10xn matrix
%load('y.mat');
y = [1; 2; 3; 4; 5]; % <== replace load temporarily
% Preallocate output array
q = zeros(10, length(y)); % <== preallocate for speed
for i = 1:length(y)
q(y(i),i) = 1; % <== Set element at y(ith) row and ith column of q to 1
endfor
Killing the loop
Either of these loops will give you the desired results, but you can do this whole operation without a loop. This answer summarizes different ways to do this, but I'll just show you the first one using sub2ind:
function q = convert
% Convert y matrix values to 10xn matrix
%load('y.mat');
y = [1; 2; 3; 4; 5]; % <== replace load temporarily
% Preallocate output array
q = zeros(10, length(y)); % <== preallocate for speed
idx = sub2ind(size(q), y, [1:length(y)].');
q(idx) = 1;
Final note
It's best not to use i as a variable name in Octave/MATLAB. It's natural in other languages, but in MATLAB i (or j) is the imaginary unit. If you use i as a variable, it shadows that constant. That doesn't make a difference if you use 1i (or 1j) when assigning complex values, but you're going to have to remember to do that and at some point you're going to forget.

Iterating through matrix rows in Octave without using an index or for loop

I am trying to understand if it's possible to use Octave more efficiently by removing the for loop I'm using to calculate a formula on each row of a matrix X:
myscalar = 0
for i = 1:size(X, 1),
myscalar += X(i, :) * y(i) % y is a vector of dimension size(X, 1)
...
The formula is more complicate than adding to a scalar. The question here is really how to iterate through X rows without an index, so that I can eliminate the for loop.
Yes, you can use broadcasting for this (you will need 3.6.0 or later). If you know python, this is the same (an explanation from python). Simply multiply the matrix by the column. Finnaly, cumsum does the addition but we only want the last row.
newx = X .* y;
myscalars = cumsum (newx, 1) (end,:);
or in one line without temp variables
myscalars = cumsum (X .* y, 1) (end,:);
If the sizes are right, broadcasting is automatically performed. For example:
octave> a = [ 1 2 3
1 2 3
1 2 3];
octave> b = [ 1 0 2];
octave> a .* b'
warning: product: automatic broadcasting operation applied
ans =
1 0 6
1 0 6
1 0 6
octave> a .* b
warning: product: automatic broadcasting operation applied
ans =
1 2 3
0 0 0
2 4 6
The reason for the warning is that it's a new feature that may confuse users and is not existent in Matlab. You can turn it off permanentely by adding warning ("off", "Octave:broadcast") to your .octaverc file
For anyone using an older version of Octave, the same can be accomplished by calling bsxfun directly.
myscalars = cumsum (bsxfun (#times, X, y), 1) (end,:);