cumulative frequency count of identical elements in a vector - matlab - matlab

I have a trouble find a matlab function/code to do following task
I have a vector C = [1 1 2 2 2 3 3 4]
I need resulting vector Y = [1 2 1 2 3 1 2 1]

You could create a function like the following:
C = [1 1 2 2 2 3 3 4]
Y = zeros(1,length(C))
helper = zeros(1,max(C)) % stores the count for each value
for i=1:length(C)
helper(C(i)) = helper(C(i))+1; %increases the count for the value in C(i)
Y(i) = helper(C(i));
end
Hope that helps

Try this out, if you want it in a one-liner, this will work...
Y = sum(cumsum(meshgrid(C)==meshgrid(C)',2).*(meshgrid(C)==meshgrid(C)').*eye(length(A)),1);
Not the prettiest, but it will work (you can always split it up to make it clearer)

Related

count adjacent elements in vector with repetitions - matlab

v = [1,1,1,2,3,3,4,4,4,4,2,3,3,3,1,1]
I'm looking for a way to count adjacent elements in vector c without loosing the repetitions.
This is the desired output:
c =
3 1 2 4 1 3 2
Use diff() to spot the change points, then get the indexes of those points.
id = diff(v)==0;
idx = strfind([id 0], 0);
c = [idx(1) diff(idx)]
Output:
c =
3 1 2 4 1 3 2
Answer from Mathworks
% code
v = [1,1,1,2,3,3,4,4,4,4,2,3,3,3,1,1];
c = diff([0 find(diff(v)) numel(v)])
% output
c = [3 1 2 4 1 3 2]

Matrix operations matlab to move values around

I have a matrix that I'd like to create a new ordering of, for example,
vals = [1 2; 3 4]
I also have two matrices, new_x and new_y such that new_x(a,b) = j and new_x(a,b) = k means that I want the value at vals (a,b) to be mapped to new_vals(j,k).
For example, given
new_x = [1 2; 2 1]
new_y = [2 2; 1 1]
I'd want
new_vals = [4 3; 1 2]
I understand that I could just write two for loops to build the new array, but matlab is notoriously good at providing operations on entire matricies. My question is, how would I build new_vals without the for loops?
Basically you are trying to get a matrix that when indexed with new_x and new_y would give us vals, i.e. -
output(new_x(1,1),new_y(1,1)) must be equal to vals(1,1),
output(new_x(1,2),new_y(1,2)) must be equal to vals(1,2) and so on.
We will try to verify this later on. For now, here's one solution using linear indexing -
nrows = size(vals,1); %// Store number of rows
%// Calculate linear indices
idx = (new_x + (new_y-1)*nrows);
%// Trace/map back to sorted version of "1:numel(vals)"
[~,traced_back_idx] = sort(idx(:));
%// Index into vals with traced back linear indices & then reshape & transpose
out = reshape(vals(traced_back_idx),[],nrows).'
Here's another and possibly faster way -
out = nan(size(vals));
out((new_x + (new_y-1)*nrows)) = vals;
out = out.'
As discussed earlier for verification, let's index into out with new_x and new_y and that should match up with vals. Here's a code to do so -
for ii = 1:size(out,1)
for jj = 1:size(out,2)
check_back(ii,jj) = out(new_y(ii,jj),new_x(ii,jj));
end
end
Sample runs -
Case #1 (sample from question):
vals =
1 2
3 4
new_x =
1 2
2 1
new_y =
2 2
1 1
new_vals =
4 3
1 2
out =
4 3
1 2
check_back = (must be same as vals)
1 2
3 4
Case #2:
vals =
1 2 5
3 4 5
6 8 3
new_x =
1 2 3
3 1 2
3 2 1
new_y =
2 2 3
2 1 1
1 3 3
out =
4 5 6
1 2 3
3 8 5
check_back = (must be same as vals)
1 2 5
3 4 5
6 8 3
I think i see what you are trying to do here. new_x and new_y are just coordinates for the new_val matrix rigth? The problem is tha what you are trying to do only works for vectors, not for matrix, so the only way is to transform the matrix into a vector, reorder the values and then go back to matrix like:
vals = [1 ,2; 3, 4];
A=reshape(vals,1,4); % A is a vector [ 1 3 2 4]
new_coord=[2,3,4,1];
B(new_c)=A; %B is [4 1 3 2]
new_val=reshape(B,2,2) %back to matrix
Obtainig new_val=[4 3; 1 2]. Also B=A(new_c) is also allowed but with different coordinates, eventhoug is much easy to think the rigth coordinates in that way.
I am sure there must be a way to include the new_x matrix and transform everything into new_coord

generate Combinations from a value in matlab

How to generate the different combinations possible for a certain number
Example:
m=2 gives:
[1 1;1 2;2 1;2 2]
m=3 gives:
[1 1;1 2;1 3;2 1;2 2;2 3;3 1;3 2;3 3]
and so on...
using perms([1 2]) generates [1 2;2 1] only
You can use ndgrid:
m = 3;
[A,B] = ndgrid(1:m);
Here A and B look like this:
A =
1 1 1
2 2 2
3 3 3
B =
1 2 3
1 2 3
1 2 3
So you can concatenate them vertically to get the combinations. Using the colon operator transforms the matrices into column-vectors, i.e. listing all the elements column-wise. Therefore, you could use either
P = sortrows([A(:), B(:)])
or
P = [B(:) A(:)] %// Thanks #knedlsepp :)
to get sorted combinations.
P now looks like this:
P =
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
Note that your question is highly related to the following, where the goal is to find combinations from 2 vectors.: How to generate all pairs from two vectors in MATLAB using vectorised code?. I suggest you look at it as well to get more ideas.
That being said the question might be a duplicate...anyhow hope that helps.
It's a little tricky, as nchoosek can not be used straight out of the box:
n = 3;
X = nchoosek([1:n, n:-1:1],2);
Y = unique(X,'rows','legacy');
respectively in one line:
Y = unique(nchoosek([1:n, n:-1:1],2),'rows','legacy');

matlab indexing with multiple condition

I can't figure out how to create a vector based on condition on more than one other vectors. I have three vectors and I need values of one vector if values on other vectors comply to condition.
As an example below I would like to choose values from vector a if values on vector b==2 and values on vector c==0 obviously I expect [2 4]
a = [1 2 3 4 5 6 7 8 9 10];
b = [1 2 1 2 1 2 1 2 1 2];
c = [0 0 0 0 0 1 1 1 1 1]
I thought something like:
d = a(b==2) & a(c==0)
but I have d = 1 1 1 1 1 not sure why.
It seems to be basic problem but I can find solution for it.
In your case you can consider using a(b==2 & c==0)
Use ismember to find the matching indices along the rows after concatenating b and c and then index to a.
Code
a(ismember([b;c]',[2 0],'rows'))
Output
ans =
2
4
You may use bsxfun too for the same result -
a(all(bsxfun(#eq,[b;c],[2 0]'),1))
Or you may just tweak your method to get the correct result -
a(b==2 & c==0)

put random position set of number with conditional repeat

I have this set of number a=[1 2 3]. And I want to put this number randomly into matrix 7 x 1, and number 1 must have 2 times, number 2 must have 3 times and number 3 must have 2 times.
The sequence is not necessary. The answer look like.
b=[1 2 2 2 1 3 3]'
Try randperm:
a=[1 2 3];
samps = [1 1 2 2 2 3 3]; % specify your desired repeats
samps = samps(randperm(numel(samps))); % shuffle them
b = a(samps)
Or, instead of specifying samps explicitly, you can specify the number of repetitions for each element of a and use arrayfun to compute samps:
reps = [2 3 2];
sampC = arrayfun(#(x,y)x*ones(1,y),a,reps,'uni',0);
samps = [sampC{:}];
samps = samps(randperm(numel(samps))); % shuffle them
b = a(samps)
%how often each value should occure
quantity=[2,2,3]
%values
a=[1,2,3]
l=[]
%get list of all values
for idx=1:numel(a)
l=[l,ones(1,quantity(idx))*v(idx)]
end
%shuffle l
l=l(randperm(numel(l)))