How to add value at end of row in a matrix

11 visualizzazioni (ultimi 30 giorni)
It is a very basic question but I could not figure how to do it without a for loop.
I have two vectors R and C of same length
R'=[2 4 5 2]
C'=[1 3 6 7]
I want to have
A=
[0 0
1 7
0 0
3 0
6 0]
Basically R is for the rows and I want to have the content of C in the corresponding row in matrix A
If I do
A(R)=C
it is going to be a vector not a matrix and the newest value will erase the oldest value in each row
A(R,:) will assign the value to the whole line which is not also what I want.
how can I increase the index of the column if there is more than one entry for each row?
  1 Commento
Muhammad Usman Saleem
Muhammad Usman Saleem il 11 Apr 2016
"Basically R is for the rows and I want to have the content of C in the corresponding row in matrix A"
What is meany by R is for rows, is this means you want A matrix rows as no of rows in R? and remaining portion of line is totally unable to understand ,plz

Accedi per commentare.

Risposta accettata

Stephen23
Stephen23 il 11 Apr 2016
Modificato: Stephen23 il 11 Apr 2016
Without any loops:
R = [2;4;5;2];
C = [1;3;6;7];
[~,X] = sort(R);
[~,~,Y] = unique(R);
Z = accumarray(Y,ones(size(R)),[],@(v){v});
Y(X) = cell2mat(cellfun(@cumsum,Z,'UniformOutput',false));
A = zeros(max(R),max(Y));
A(sub2ind(size(A),R,Y)) = C
creates this output:
A =
0 0
1 7
0 0
3 0
6 0
  4 Commenti
Stephen23
Stephen23 il 11 Apr 2016
Modificato: Stephen23 il 12 Apr 2016
@etudiant_is: here is the code with comments to help you:
% sort the values of R:
[~,X] = sort(R);
% get indices/groups of unique values in R:
[~,~,Y] = unique(R);
% collect each group's values into a vector in a cell array:
Z = accumarray(Y,ones(size(R)),[],@(v){v});
% create consecutive column indices for each value in each group:
Y(X) = cell2mat(cellfun(@cumsum,Z,'UniformOutput',false));
% preallocate an output matrix of the correct size:
A = zeros(max(R),max(Y));
% use linear indices to allocate the original values into the output matrix:
A(sub2ind(size(A),R,Y)) = C
And in particular the lines that you ask about. The vector Y contains a list of unique groups/rows. For your example this is
>> [~,~,Y] = unique(R)
Y =
1
2
3
1
We use these group indices to collect some 1's together in a cellarray, they will be later converted into the column indices:
>> Z = accumarray(Y,ones(size(R)),[],@(v){v});
>> Z{:}
ans =
1
1
ans =
1
ans =
1
To convert these vectors of 1's into consecutive column indices we use cumsum, which has to be encapsulated in a cellfun because the groups of ones are held in a cell array:
>> tmp = cellfun(@cumsum,Z,'UniformOutput',false);
>> tmp{:}
ans =
1
2
ans =
1
ans =
1
These are joined together using cell2mat to give one numeric vector:
>> cell2mat(tmp)
ans =
1
2
1
1
Now we have to right column indices, but in the wrong order. We can use the sort index X to put them back into the correct order:
>> Y(X) = cell2mat(tmp)
Y =
1
1
1
2
I reused the variable Y because this allow us to keep its shape (column vector), otherwise a reshape would be required. Now we have a list of row indices R and column indices Y. These can be used with sub2ind to get the linear indices, and these then used to allocate the value allocated to the output matrix.
The @ is used to define a function handle, which allows the function to be passed around like a variable. This is quite handy!
etudiant_is
etudiant_is il 11 Apr 2016
Thanks for the detailed explanation. I will take my time to understand it.

Accedi per commentare.

Più risposte (2)

Andrei Bobrov
Andrei Bobrov il 11 Apr 2016
R=[2 4 5 2]
C=[1 3 6 7]
[b,ii] = histc(R(:),unique(R));
out = zeros(max(R),max(b));
for jj = 1:numel(b)
out(R(find(jj==ii,1,'first')),1:b(jj)) = C(jj==ii);
end
  1 Commento
etudiant_is
etudiant_is il 11 Apr 2016
Thanks for your answer, but why do you take only first value in find?

Accedi per commentare.


Muhammad Usman Saleem
Muhammad Usman Saleem il 11 Apr 2016
Modificato: Muhammad Usman Saleem il 11 Apr 2016
I unable to understand what you want in your final matrix.
First see if you wanting column vectors these are not correct format in matlab, see it below
>> R'=[2 4 5 2]
C'=[1 3 6 7]
output
R'=[2 4 5 2]
|
Error: The expression to the left of the equals sign is not a
valid target for an assignment.
Now try this if you want column vectors
>> R=[2 4 5 2]'
R =
2
4
5
2
>> C=[1 3 6 7]'
C =
1
3
6
7
Now
>> A(R)=C
A =
0 7 0 3 6
  1 Commento
etudiant_is
etudiant_is il 11 Apr 2016
For the transpose, I just wanted to write the vector here horizontally to be more clear, that is all.
What I want is to take the number of the rows from vector R and then see what is in C and put it in these corresponding rows. In my example, I have
R(1)=2 and C(1)=1
so I am going to have
A(2, 1)=1
then at the end of R, I have
R(4)=2 and
C(4)=7 again
so I will have
A(2,2)= 7 and so on.
Hope it is clearer.

Accedi per commentare.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by