How to add value at end of row in a matrix

17 Ansichten (letzte 30 Tage)
etudiant_is
etudiant_is am 11 Apr. 2016
Bearbeitet: Stephen23 am 12 Apr. 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 Kommentar
Muhammad Usman Saleem
Muhammad Usman Saleem am 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

Melden Sie sich an, um zu kommentieren.

Akzeptierte Antwort

Stephen23
Stephen23 am 11 Apr. 2016
Bearbeitet: Stephen23 am 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 Kommentare
Stephen23
Stephen23 am 11 Apr. 2016
Bearbeitet: Stephen23 am 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 am 11 Apr. 2016
Thanks for the detailed explanation. I will take my time to understand it.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (2)

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

Melden Sie sich an, um zu kommentieren.


Muhammad Usman Saleem
Muhammad Usman Saleem am 11 Apr. 2016
Bearbeitet: Muhammad Usman Saleem am 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 Kommentar
etudiant_is
etudiant_is am 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.

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Matrices and Arrays finden Sie in Help Center und File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by