given a vector and matrix A and B, how to multiply each element of A as a scalar to B then add up each of the new matrix, without using a for loop.
What i mean is:
A = [1;2;3]
B = [1 2;3 4 ;5 6]
C = (A(1) * B) + (A(2) * B) + (A(3) * B)
ans =
6 12
18 24
30 36
C = sum(C)
C =
54 72
but I can't do it manually because the vector is too long.
You can use the following command:
sum(reshape(sum(B(:)*A.',2),size(B)))
Explanation:
B(:)*A'
Flatten out B and multiply each element of it with each element of A.
sum(B(:)*A.',2)
Sum across the 'A' dimension (rows).
reshape(sum(B(:)*A.',2),size(B))
Reshape to get back to the original dimensions of B.
sum(reshape(sum(B(:)*A.',2),size(B)))
Sum across the columns as you wanted.
Edit
Suggestion from #verbatros which work when A is row vector as well:
sum(reshape(sum(B(:)*A(:).',2),size(B)))
Very easy:
A = [1;2;3]
B = [1 2;3 4 ;5 6]
C = sum (A(:)) .* sum (B)
C =
54 72
Related
I have a 4x5 matrix called A from which I want to select randomly 3 rows, then 4 random columns and then select those elements which coincide in those selected rows and columns so that I have 12 selected elements.Then I want to create a diagonal matrix called B which will have entries either 1 or 0 so that multiplication of that B matrix with reshaped A matrix (20x1) will give me those selected 12 elements of A.
How can I create that B matrix? Here is my code:
A=1:20;
A=reshape(A,4,5);
Mr=4;
Ma=3;
Na=4;
Nr=5;
M=Ma*Mr;
[S1,S2]=size(A);
N=S1*S2;
y2=zeros(size(A));
k1=randperm(S1);
k1=k1(1:Ma);
k2=randperm(S2);
k2=k2(1:Mr);
y2(k1,k2)=A(k1,k2);
It's a little hard to understand what you want and your code isn't much help but I think I've a solution for you.
I create a matrix (vector) of zeros of the same size as A and then use bsxfun to determine the indexes in this vector (which will be the diagonal of B) that should be 1.
>> A = reshape(1:20, 4, 5);
>> R = [1 2 3]; % Random rows
>> C = [2 3 4 5]; % Random columns
>> B = zeros(size(A));
>> B(bsxfun(#plus, C, size(A, 1)*(R-1).')) = 1;
>> B = diag(B(:));
>> V = B*A(:);
>> V = V(V ~= 0)
V =
2
3
4
5
6
7
8
9
10
11
12
13
Note: There is no need for B = diag(B(:)); we could have simply used element by element multiplication in Matlab.
>> V = B(:).*A(:);
>> V = V(V ~= 0)
Note: This may be overly complex or very poorly put together and there is probably a better way of doing it. It's my first real attempt at using bsxfun on my own.
Here is a hack but since you are creating y2 you might as well just use it instead of creating the useless B matrix. The bsxfun answer is much better.
A=1:20;
A=reshape(A,4,5);
Mr=4;
Ma=3;
Na=4;
Nr=5;
M=Ma*Mr;
[S1,S2]=size(A);
N=S1*S2;
y2=zeros(size(A));
k1=randperm(S1);
k1=k1(1:Ma);
k2=randperm(S2);
k2=k2(1:Mr);
y2(k1,k2)=A(k1,k2);
idx = reshape(y2 ~= 0, numel(y2), []);
B = diag(idx);
% "diagonal" matrix 12x20
B = B(all(B==0,2),:) = [];
output = B * A(:)
output =
1
3
4
9
11
12
13
15
16
17
19
20
y2 from example.
y2 =
1 0 9 13 17
0 0 0 0 0
3 0 11 15 19
4 0 12 16 20
I have a picture matrix A, the size of which is 200*3000 double. And I have another picture matrix B, the size of which is 200*1000 double. The 1000 columns of matrix B exactly comes from the columns of matrix A. My question is:
How to get a matrix C with the same size of matrix A, but only keep the original values of columns in matrix B? I mean the size of matrix C is 200*3000 double, but only 1000 columns have the same values as matrix B. The other 2000 columns will be set to another value d, that is my second question, what is the value I should set for d, so that the picture matrix C can distinguish from picture matrix A?
Use ismember with the 'rows' option. Here's an example:
A = [1 2 3 4; 5 6 7 8]; %// example A
B = [3 10 1; 7 20 5]; %// example B
val = NaN; %// example value to indicate no match
C = A; %// initiallize
ind = ismember(A.',B.','rows'); %// matching columns
C(:,~ind) = val; %// set non-matching columns to val
Equivalently, you coud replace ismember by bsxfun, so that line becomes
ind = any(all(bsxfun(#eq, A, permute(B, [1 3 2])), 1), 3);
In this example,
A =
1 2 3 4
5 6 7 8
B =
3 10 1
7 20 5
C =
1 NaN 3 NaN
5 NaN 7 NaN
I am currently experimenting with Matlab functions. Basically I am trying to perform a function on each value found in a matrix such as the following simple example:
k = [1:100];
p = [45 60 98 100; 46 65 98 20; 47 65 96 50];
p(find(p)) = getSum(k, find(p), find(p) + 1);
function x = getSum(k, f, g, h)
x = sum(k(f:g));
end
Why the corresponding output matrix values are all 3, in other words why all indices are depending on the first calculated sum?
The output is the following:
p =
3 3 3 3
3 3 3 3
3 3 3 3
f:g returns the value between f(1,1) and g(1,1), so 1:2.
find(p) returns the indices of non zero values. Since all values are non-zero, you get all indices.
So if we break down the statement p(find(p)) = getSum(k, find(p), fin(p) + 1)
We get
find(p) = 1:12
We then get
f = 1:12 and g = 2:13 which lead to k = 1:2 (as explained above)
finally sum(1:2) = 3
And this value is apply over p(1:12), which is the same as p(:,:) (all the matrix)
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Sort a matrix with another matrix
The Matrix A ('10 x 1000' all numbers) look like this:
score(1.1) score(1.2) score(1.3)....score(1.1000)
score(2.1) score(2.2) score(2.3)....score(1.1000)
...
The Matrix B ('1 x 1000' all numbers):
Return(1) Return(2) Return(3) .....Return(1.1000)
Every time I sort a row of Matrix A, I want to sort Matrix B based on the order of the sorted row in Matrix A. Because there are 10 rows in Matrix A, Matrix B will be sorted 10 times and generate a new Matrix C ('10 x 1000') like this: (I am looking for a script to generate this Matrix C)
Return(3) Return(25) Return(600) .......Return(1000)
Return(36)Return(123) Return(2)........Return(212)
....
....
This should do what you want:
A = randn(10,1000);
B = randn(1,1000);
C = zeros(size(A));
for i = 1:10
[a idx] = sort(A(1,:));
A(i,:) = a;
C(i,:) = B(idx);
end
Now the rows of A are sorted, and the rows of C contain the corresponding sorted B.
This solution is a bit more compact, and it's also good to get used to doing this kind of solution for efficiency when your matrices get big. You can solve your problem with two ideas:
In [a, ix] = sort(X), a is a column-sorted version of X, and ix stores which rows moved where in each column. Thus if we do [a, ix] = sort(X.').'; (where the dot-apostrophe is the transpose) we can sort the rows.
B(ix) where ix is a bunch of indeces will make a matrix the same size as ix with the i-jth element being B at ix(i,j)
Then you just need to reshape it. So you can do:
A = rand(4,8);
B = rand(1,8);
n = size(A,1);
m = size(A,2);
[~,ix] = sort(A.');
C = reshape(B(ix'),n,m);
If I understand your question correctly the following should work. Using some sample scores:
>> score = [1 4 7 9; 3 5 1 7; 9 3 1 6]
score =
1 4 7 9
3 5 1 7
9 3 1 6
and sample return vector:
>> r = [10 20 30 40]
r =
10 20 30 40
Transpose the scores and sort since the SORT command works on columns of a matrix. We're only interested in the indices of the sorted values:
>> [~, ix] = sort(score')
ix =
1 3 3
2 1 2
3 2 4
4 4 1
Now transpose these indices and use them to reference the return values:
>> answer = r(ix)'
answer =
10 20 30 40
30 10 20 40
30 20 40 10
How can I combine 2 matrices A, B into one so that the new matrix C = row 1 of A, followed by row 1 of B, then row 2 of A, row 2 of B, row 3 of A, row 3 of B, etc? Preferably without a for loop?
ex: A = [1 2 3; 4 5 6], B = [5 5 5; 8 8 8].
AB = [1 2 3; 5 5 5; 4 5 6; 8 8 8].
All you need is a bit of catenation and reshaping. First, you catenate along dimension 2, then you transpose, and linearize (AB(:)), so that you get a vector whose first three elements are the first row of A, then the first row of B, then the second row of A, etc. All that's left in the end is calling reshape to put everything back into an array again.
nColumns = size(A,2);
AB = [A,B]';
AB = reshape(AB(:),nColumns,[])';
Alternatively, you can construct AB directly via indexing. In this case, A is allowed to have one more row than B. This is probably faster than the above.
[nRowsA,nCols] = size(A);
nRowsB = size(B,1);
AB = zeros(nRowsA+nRowsB,nCols);
AB(1:2:end,:) = A;
AB(2:2:end,:) = B;