I want to take an arbitrary 1D vector a = [k] and b = [m] and form the matrix of ordered pairs c = [2 x k x m] such that $c->(:,(i),(j)) = [ $a->(i), $b->(j) ]. I.e. the set of all ordered pairs of the elements in a and b a.k.a the cartesian product.
Of course I could use a loop and the [glue] function to accomplish this, but that isn't in the spirit of Perl/PDL. Is there a fancy method that involves slices, dummy dimensions, and glue that gets me there?
Also, using Math::Cartesian::Product (as answered here: In Perl, how can I get the Cartesian product of multiple sets? is cheating! :3 I want straight perl/PDL and hopefully learn something in the process.
I got something that meets my criteria:
my $a = pdl 1,2,3,4;
my $b = pdl 5,6,7;
print "a = $a\n";
print "b = $b\n";
print "dummy dimensioned:\n";
$a = $a->dummy(0,$b->dim(0));
print "a".$a->shape." = $a\n";
$b = $b->dummy(0, $a->dim(1))->transpose;
print "b".$b->shape." = $b\n";
print "Glued together:\n"
my $c = $a->dummy(0,1)->glue(0, $b->dummy(0,1));
print "c".$c->shape." = $c\n";
a = [1 2 3 4]
b = [5 6 7]
dummy dimensioned:
a[3 4] =
[
[1 1 1]
[2 2 2]
[3 3 3]
[4 4 4]
]
b[3 4] =
[
[5 6 7]
[5 6 7]
[5 6 7]
[5 6 7]
]
Glued together:
c[2 3 4] = [[[1 5][1 6][1 7]][[2 5][2 6][2 7]][[3 5][3 6][3 7]][[4 5][4 6][4 7]]]
Related
I have a matrix
A = [1,2;3,4];
I would like to generate a new matrix B, which contains all permutations over the columns for each row.
B = [1,2;2,1;3,4;4,3]
Is there a one-liner solution?
I could only think of a solution incorporating cell arrays, thus I'm not sure, if that is "efficient" at all. Also, have a look at the limitations of perms.
% Input.
A = [1, 2; 3, 4]
% Expected output.
B = [1, 2; 2, 1; 3, 4; 4, 3]
% Calculate output.
C = sortrows(cell2mat(cellfun(#(x) perms(x), mat2cell(A, ones(1, size(A, 1)), 2), 'UniformOutput', false)))
A =
1 2
3 4
B =
1 2
2 1
3 4
4 3
C =
1 2
2 1
3 4
4 3
I found a solution to my own question.
n = 2; % size of permutations
perm_index = perms(1:n); % index of the matrix to perm
perm_length = size(perm_index,1);
data = [3,4;5,6];
data_length = size(data,1);
output_length = perm_length* data_length;
output = reshape(data(:,perm_index), output_length,n);
%Final output
output = [4,3;6,5;3,4;5,6]
I couldn't find any one-liner solution. Hope this one is simpler enough:
A = [1, 2, 3; 4, 5, 6];
B = [];
for i=1:size(A,1)
B = [B ; perms(A(i, :))];
end
Read about the function nchoosek
A = [1 2 3 4] ;
B = nchoosek(A,2)
I have A matrix which is 16x16x155460. I have a B vector which is 12955x1. I want to multiply each 1:16x1:16x1+12*n:12+12*nwith the elements of B(n). So my goal is to find the weighted sum of the A according to B. My way to do this as follows (I don't want to use for-loop and my method gives wrong answer, I could not obtain the 1:12 vectors which is consecutive) :
B = repmat(B,[1 16 16]);
B = permute(B,[2 3 1]);
B = repmat(B,[1 1 12]);
result = B.*(A);
As a small example n=2 :
A(:,:,1)=[1 2; 3 4]
A(:,:,2)=[1 2; 3 4]
A(:,:,3)=[1 2; 3 4]
A(:,:,4)=[1 2; 3 4]
B = [2,3]
Result would be:
result(:,:,1)=A(:,:,1)*B(1);
result(:,:,2)=A(:,:,2)*B(1);
result(:,:,3)=A(:,:,1)*B(2);
result(:,:,4)=A(:,:,2)*B(2);
If I understood the problem correctly, you can use the powerful trio of bsxfun, permute and reshape to solve it, like so -
[M,N,R] = size(A);
mult_out = bsxfun(#times,reshape(A,M,N,numel(B),[]),permute(B(:),[4 3 1 2]))
out = reshape(mult_out,M,N,[])
In python one can use zip to loop multiple vectors or enumerate to get the current index of the looped vector like so
one = ['A', 'B', 'C']
two = [1, 2, 3]
for i, j in zip(one, two):
print i, j
for j, i in enumerate(one):
print i, two[j]
Gives
>>>
A 1
B 2
C 3
A 1
B 2
C 3
In MATLAB it's possible to do
one = {'A' 'B' 'C'};
two = [1 2 3];
for i = 1:1:length(one)
printf('%s %i\n', one{i}, two(i));
endfor
j = 1;
for i = one
printf('%s %i\n', i{1}, two(j));
j = j + 1;
endfor
giving
A 1
B 2
C 3
A 1
B 2
C 3
So is one of those two options the common way how one would do it in MATLAB, i. e. to loop through several vectors "in parallel" or is there another, maybe better way?
Bonus:
two = [1 2 3];
two = [1, 2, 3];
Both of these lines give the same output in the upper MATLAB program. Whats the difference?
Using printf, or fprintf in Matlab, is pretty good. The Matlab code for your first approach is
one = {'A' 'B' 'C'};
two = [1 2 3];
for ii = 1:length(one)
fprintf('%s %i\n', one{ii}, two(ii));
end
It's also possible to put the strings into a cell array, without any for loop.
s = cellfun(#(a,b) [a,' ',b], one', ...
arrayfun(#num2str, two', 'UniformOutput', false),....
'UniformOutput', false)
Bonus:
>> A = [1;2;3]
A =
1
2
3
>> A = [1 2 3]
A =
1 2 3
>> A = [1,2,3]
A =
1 2 3
>> A = [1,2,3;4 5 6;7,8 9]
A =
1 2 3
4 5 6
7 8 9
>>
Bonus 2:
Using i and j is bad. See - Using i and j as variables in Matlab
Let's say I have this structure:
Results(i,j).fo
Results(i,j).co
where i=19 and j=30. How can I save in a ixj matrix all Results(i,j).fo? Or even better, How can I say to bootci to read only Results(i,j).fo
Media_tot = mean(Matrix,2)
ci = bootci(1000, #mean, Matrix');
ci = abs(ci' - repmat(Media_tot,1,2));
hE = errorbar(xdata_m, ydata_m, ci(:,1), ci(:,2));
I think this should work for your first question:
reshape([Results.fo], 19, 30)
e.g.
%// Make a 3x3 matrix of structs with 2 fields
A = [];
for k = 1:9
A(k).x = k;
A(k).y = 9-k;
end
A= reshape(A,3,3)
Now
reshape([A.x], 3,3)
ans =
1 4 7
2 5 8
3 6 9
and
reshape([A.y], 3,3)
ans =
8 5 2
7 4 1
6 3 0
Given an array of equivalent structures, e.g.
Results = [ struct('fo',1, 'co',2) struct('fo',10, 'co',20); struct('fo',100, 'co',200) struct('fo',1000, 'co',2000) ]
You can access all 'fo` using the square brackets
all_fo = [Results.fo]
% >> [1 100 10 1000]
However, they are then in a 1D-array, to get them in the original format, use
all_fo = reshape([Results.fo], size(Results))
% >> [1 10; 100 1000]
I have two 2-dimensional matrices A,B, where B is produced by a (row-wise) permutation of A. There are a few repetitive records in A (and so in B). I want to find the mapping that produced B. I am using Matlab. Only one solution is sufficient for me.
Example:
A = [ 2 3 4; 4 5 6; 2 3 4];
B = [ 4 5 6; 2 3 4; 2 3 4];
The mapping would be:
p = [3 1 2] // I want this mapping, however the solution p= [2 1 3] is also correct and acceptable
where A = B(p,:) in Matlab. // EDITED
Regards
low hanging fruits first.
Suppose there are no duplicate rows:
% compute the permutation matrix
P = all( bsxfun( #eq, permute( A, [1 3 2]),permute(B,[3 1 2]) ), 3 );
[~, p] = max(P, [], 2 ); % gives you what you want
If there are duplicates, we need to "break ties" in the rows/columns of P:
n = size(A,1);
bt = abs( bsxfun(#minus, 1:n, (1:n)' ) )/n; %//'
[~, p] = max( P+bt, [], 2 );
Since we know that A and B always have the same rows, let's look for a transformation that will convert each one to a common identical representation. How about sort?
[As, Ai] = sortrows(A);
[Bs, Bi] = sortrows(B);
Now A(Ai,:) == B(Bi,:), so all we have to do is find the indices for Bi that match Ai. Bi is a forward mapping, Ai is a reverse mapping. So:
p = zeros(size(A,1),1);
p(Ai) = Bi;
(Answer edited to match edit of problem statement)
Here is a solution using sort() to get around the problem of needing to generate all permutations.
The idea is to sort both A and B which will produce the same sorted matrix. The permutation can now be found by using the indices IA and IB that produce the two sorted matrices.
A = [ 2 3 4; 4 5 6; 2 3 4];
B = [ 4 5 6; 2 3 4; 2 3 4];
[CA,IA]=sort(A,1)
[CB,IB]=sort(B,1)
idxA = IA(:,1)
idxB = IB(:,1)
[~, idxB_inverse] = sort(idxB)
idxA(idxB_inverse)