How to separate columns in matlab - matlab

if you have an array from a for loop
for a =1:3;
for b=1:3;
for c=1:3;
disp([a(:) b(:) c(:)])
end
end
end
and you want to separate each column of the output
to separate each column you need this code: assuming the data stored in 'A' array:
yy = A(:,1)
yx = A(:,2)
yz = A(:,3)
and so on...
but what if you don't know the size of your array or if you have m x n array? what is the general code to separate column? thanks

You can do it like this:
y = [1 1 1 1 1
1 2 3 1 1
1 0 2 2 1]
[m,n] = size(y)
for i=1:n
C{i} = y(:,i);
end
Now you can access each column via C(1), C(2), C(3), etc. C looks like this:
C =
{
[1,1] =
1
1
1
[1,2] =
1
2
0
[1,3] =
1
3
2
}
The output of just C(2) is:
ans =
{
[1,1] =
1
2
0
}
That said, it is probably better to stick with the code that you have to directly access the column from the matrix (y(:,1)), instead of creating a bunch of dynamic variables.

How would you manage these columns separated ? It's not a good idea to name them as y1, y2, ... .
If you want to pick up the i-th column, just use y(:, i). That's a lot easier to use.

Related

count co-occurrence neighbors in a vector

I have a vector : for example S=(0,3,2,0,1,2,0,1,1,2,3,3,0,1,2,3,0).
I want to count co-occurrence neighbors, for example the first neighbor "o,3" how many times did it happen till the end of the sequence? Then it investigates the next pair"2,0" and similarly do it for other pairs.
Below is a part of my code:
s=size(pic);
S=s(1)*s(2);
V = reshape(pic,1,S);
min= min(V);
Z=zeros(1,S+1);
Z(1)=min;
Z(2:end)=V;
for i=[0:2:length(Z)-1];
contj=0
for j=0;length(Z)-1;
if Z(i,i+1)= Z(j,j+1)
contj=contj+1
end
end
count(i)= contj
end
It gives me this error:
The expression to the left of the equals sign is not a valid target for an assignment
in this line:
if Z(i,i+1)= Z(j,j+1)
I read similar questions and apply the tips on it but they didn't work!
If pairs are defined without overlapping (according to comments):
S = [0,3,2,0,1,2,0,1,1,2,3,3,0,1,2,3]; %// define data
S2 = reshape(S,2,[]).'; %'// arrange in pairs: one pair in each row
[~, jj, kk] = unique(S2,'rows'); %// get unique labels for pairs
pairs = S2(jj,:); %// unique pairs
counts = accumarray(kk, 1); %// count of each pair. Or use histc(kk, 1:max(kk))
Example: with S as above (I introduce blanks to make pairs stand out),
S = [0,3, 2,0, 1,2, 0,1, 1,2, 3,3, 0,1, 2,3];
the result is
pairs =
0 1
0 3
1 2
2 0
2 3
3 3
counts =
2
1
2
1
1
1
If pairs are defined without overlapping but counted with overlapping:
S = [0,3,2,0,1,2,0,1,1,2,3,3,0,1,2,3]; %// define data
S2 = reshape(S,2,[]).'; %'// arrange in pairs: one pair in each row
[~, jj] = unique(S2,'rows'); %// get unique labels for pairs
pairs = S2(jj,:); %// unique pairs
P = [S(1:end-1).' S(2:end).']; %// all pairs, with overlapping
counts = sum(pdist2(P,pairs,'hamming')==0);
If you don't have pdist2 (Statistics Toolbox), replace last line by
counts = sum(all(bsxfun(#eq, pairs.', permute(P, [2 3 1]))), 3);
Result:
>> pairs
pairs =
0 1
0 3
1 2
2 0
2 3
3 3
>> counts
counts =
3 1 3 2 2 1
do it using sparse command
os = - min(S) + 1; % convert S into indices
% if you want all pairs, i.e., for S = (2,0,1) count (2,0) AND (0,1):
S = sparse( S(1:end-1) + os, S(2:end) + os, 1 );
% if you don't want all pairs, i.e., for S = (2,0,1,3) count (2,0) and (1,3) ONLY:
S = sparse( S(1:2:end)+os, S(2:2:end) + os, 1 );
[f s c] = find(S);
f = f - os; % convert back
s = s - os;
co-occurences and their count are in the pairs (f,s) - c
>> [f s c]
ans =
2 0 2 % i.e. the pair (2,0) appears twice in S...
3 0 2
0 1 3
1 1 1
1 2 3
3 2 1
0 3 1
2 3 2
3 3 1

Vector of the occurence number

I have a vector a=[1 2 3 1 4 2 5]'
I am trying to create a new vector that would give for each row, the occurence number of the element in a. For instance, with this matrix, the result would be [1 1 1 2 1 2 1]': The fourth element is 2 because this is the first time that 1 is repeated.
The only way I can see to achieve that is by creating a zero vector whose number of rows would be the number of unique elements (here: c = [0 0 0 0 0] because I have 5 elements).
I also create a zero vector d of the same length as a. Then, going through the vector a, adding one to the row of c whose element we read and the corresponding number of c to the current row of d.
Can anyone think about something better?
This is a nice way of doing it
C=sum(triu(bsxfun(#eq,a,a.')))
My first suggestion was this, a not very nice for loop
for i=1:length(a)
F(i)=sum(a(1:i)==a(i));
end
This does what you want, without loops:
m = max(a);
aux = cumsum([ ones(1,m); bsxfun(#eq, a(:), 1:m) ]);
aux = (aux-1).*diff([ ones(1,m); aux ]);
result = sum(aux(2:end,:).');
My first thought:
M = cumsum(bsxfun(#eq,a,1:numel(a)));
v = M(sub2ind(size(M),1:numel(a),a'))
on a completely different level, you can look into tabulate to get info about the frequency of the values. For example:
tabulate([1 2 4 4 3 4])
Value Count Percent
1 1 16.67%
2 1 16.67%
3 1 16.67%
4 3 50.00%
Please note that the solutions proposed by David, chappjc and Luis Mendo are beautiful but cannot be used if the vector is big. In this case a couple of naïve approaches are:
% Big vector
a = randi(1e4, [1e5, 1]);
a1 = a;
a2 = a;
% Super-naive solution
tic
x = sort(a);
x = x([find(diff(x)); end]);
for hh = 1:size(x, 1)
inds = (a == x(hh));
a1(inds) = 1:sum(inds);
end
toc
% Other naive solution
tic
x = sort(a);
y(:, 1) = x([find(diff(x)); end]);
y(:, 2) = histc(x, y(:, 1));
for hh = 1:size(y, 1)
a2(a == y(hh, 1)) = 1:y(hh, 2);
end
toc
% The two solutions are of course equivalent:
all(a1(:) == a2(:))
Actually, now the question is: can we avoid the last loop? Maybe using arrayfun?

Returning the results as a vector

If I make a for-loop and return all the values in some vector in matlab as follows:
function elements(v)
for i=1:length(v)
c(i) = v(i)
end
When I run the following, I get the results as shown:
>> A = [1 2 3 4]
A =
1 2 3 4
>> elements(A)
c =
1
c =
1 2
c =
1 2 3
c =
1 2 3 4
How can I return the results as: c = [1 2 3 4] only?
Thanks.
function elements(v)
for i=1:length(v)
c(i) = v(i);
end
disp(c)
I don't know if this is gonna be what you really mean, but I'd this:
function c = so_test(v)
c = v(:)';
end
An even more compact solution
function c = elements(v)
for i=1:length(v)
c(i) = v(i);
end
Note that it does not look much different from the other solutions,
But I think that this is the what you want to do assuming you want to do something complicated/dependant on c.
If you just want all elements, just use v(:)', v or v' instead like #fpe mentioned.

how to repeat element matrix in matlab

How to repeat
A = [ 1 2 ;
3 4 ]
repeated by
B = [ 1 2 ;
2 1 ]
So I want my answer like matrix C:
C = [ 1 2 2;
3 3 4 ]
Thanks for your help.
Just for the fun of it, another solution making use of arrayfun:
res = cell2mat(arrayfun(#(a,b) ones(b,1).*a, A', B', 'uniformoutput', false))'
This results in:
res =
1 2 2
3 3 4
To make this simple, I assume that you're only going to add more columns, and that you've checked that you have the same number of columns for each row.
Then it becomes a simple combination of repeating elements and reshaping.
EDIT I've modified the code so that it also works if A and B are 3D arrays.
%# get the number of rows from A, transpose both
%# A and B so that linear indexing works
[nRowsA,~,nValsA] = size(A);
A = permute(A,[2 1 3]);
B = permute(B,[2 1 3]);
%# create an index vector from B
%# so that we know what to repeat
nRep = sum(B(:));
repIdx = zeros(1,nRep);
repIdxIdx = cumsum([1 B(1:end-1)]);
repIdx(repIdxIdx) = 1;
repIdx = cumsum(repIdx);
%# assemble the array C
C = A(repIdx);
C = permute(reshape(C,[],nRowsA,nValsA),[2 1 3]);
C =
1 2 2
3 3 4

Matlab swap

I am trying to create a function that will swap a specific number in a matrix with a specific number in the same matrix. For examlpe, if I start with A = [1 2 3;1 3 2], I want to be able to create B = [2 1 3; 2 3 1], simply by telling matlab to swap the 1's with the 2's. Any advice would be appreciated. Thanks!
If you have the following matrix:
A = [1 2 3; 1 3 2];
and you want all the ones to become twos and the twos to become ones, the following would be the simplest way to do it:
B = A;
B(find(A == 1)) = 2;
B(find(A == 2)) = 1;
EDIT:
As Kenny suggested, this can even be further simplified as:
B = A;
B(A == 1) = 2;
B(A == 2) = 1;
Another way to deal with the original problem is to create a permutation vector indicating to which numbers should the original entries be mapped to. For the example, entries [1 2 3] should be mapped respectively to [2 1 3], so that we can write
A = [1 2 3; 1 3 2];
perm = [2 1 3];
B = perm(A)
(advantage here is that everything is done in one step, and that it also works for operations more complicated than swaps ; drawback is that all elements of A must be positive integers with a known maximum)
Not sure why you would to perform that particular swap (row/column interchanges are more common). Matlab often denotes ':' to represent all of something. Here's how to swap rows and columns:
To swap rows:
A = A([New order of rows,,...], :)
To Swap columns:
A = A(:, [New order of columns,,...])
To change the entire i-th column:
A(:, i) = [New; values; for; i-th; column]
For example, to swap the 2nd and 3rd columns of A = [1 2 3;1 3 2]
A = A(:, [1, 3, 2])
A = [1 2 3; 1 3 2]
alpha = 1;
beta = 2;
indAlpha = (A == alpha);
indBeta = (A == beta);
A(indAlpha) = beta;
A(indBeta ) = alpha
I like this solution, it makes it clearer what is going on. Less magic numbers, could easily be made into a function. Recycles the same matrix if that is important.
I don't have a copy of MatLab installed, but I think you can do some thing like this;
for i=1:length(A)
if (A(i)=1), B(i) = 2, B(i)=A(i)
end
Note, that's only convert 1's to 2's and it looks like you also want to convert 2's to 1's, so you'll need to do a little more work.
There also probably a much more elegant way of doing it given you can do this sort of thing in Matlab
>> A = 1:1:3
A = [1,2,3]
>> B = A * 2
B = [2,4,6]
There might be a swapif primitive you can use, but I haven't used Matlab in a long time, so I'm not sure the best way to do it.
In reference to tarn's more elegant way of swapping values you could use a permutation matrix as follows:
>> a =[1 2 3];
>> T = [1 0 0;
0 0 1;
0 1 0];
>> b = a*T
ans =
1 3 2
but this will swap column 2 and column 3 of the vector (matrix) a; whereas the question asked about swapping the 1's and 2's.
Update
To swap elements of two different values look into the find function
ind = find(a==1);
returns the indices of all the elements with value, 1. Then you can use Mitch's suggestion to change the value of the elements using index arrays. Remeber that find returns the linear index into the matrix; the first element has index 1 and the last element of an nxm matrix has linear index n*m. The linear index is counted down the columns. For example
>> b = [1 3 5;2 4 6];
>> b(3) % same as b(1,2)
ans = 3
>> b(5) % same as b(1,3)
ans = 5
>> b(6) % same as b(2,3)
ans = 6