How to add value at end of row in a matrix

3 vues (au cours des 30 derniers jours)
etudiant_is
etudiant_is le 11 Avr 2016
Modifié(e) : Stephen23 le 12 Avr 2016
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 commentaire
Muhammad Usman Saleem
Muhammad Usman Saleem le 11 Avr 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

Connectez-vous pour commenter.

Réponse acceptée

Stephen23
Stephen23 le 11 Avr 2016
Modifié(e) : Stephen23 le 11 Avr 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 commentaires
Stephen23
Stephen23 le 11 Avr 2016
Modifié(e) : Stephen23 le 12 Avr 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 le 11 Avr 2016
Thanks for the detailed explanation. I will take my time to understand it.

Connectez-vous pour commenter.

Plus de réponses (2)

Andrei Bobrov
Andrei Bobrov le 11 Avr 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 commentaire
etudiant_is
etudiant_is le 11 Avr 2016
Thanks for your answer, but why do you take only first value in find?

Connectez-vous pour commenter.


Muhammad Usman Saleem
Muhammad Usman Saleem le 11 Avr 2016
Modifié(e) : Muhammad Usman Saleem le 11 Avr 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 commentaire
etudiant_is
etudiant_is le 11 Avr 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.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Matrix Indexing dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by