Example, i have an array :
a = [2 3 1 2 4 5 6 4];
b = sort(a);
b = [1 2 2 3 4 4 5 6];
Now i want to combine two value of a and b :
c = [21 32 12 23 44 54 65 46]
then i do the sort of c :
d = [12 21 23 32 44 46 54 65]
and i combine again from c and d (first of c, same value of second c and first d, last d) :
e = [212 321 123 232 444 546 654 465]
then i do the sort of e :
f = [123 212 232 321 444 465 546 654]
and i combine again from e and f :
g = [2123 3212 1232 2321 4444 5465 6546 4654]
so on till the length of a that equals to 8.
Please help me.
Try this:
a = [2 3 1 2 4 5 6 4]
for m=2:8
b = sort(a)
t = round(b-10*floor(b/10))
a = 10*a+t
end
It looks to me like the algorithm just adds the last digit of each sorted list onto the corresponding number in the unsorted list. t is just the last digit in b, then 10*a+t shifts the existing digits in a and puts t at the end. Apologies if I have misunderstood the objective and this is the wrong algorithm, but it works with you example. I guess you will need to convince yourself whether the code does follow your rules.
Related
I have two matrices A (51 rows X 5100 columns) and B (51rows X 5100 columns) and I want to subtract every row of A with every row of B to obtain another matric C (2601 rows X 5100 columns). How can I have the matrix C?
You can do that by
permuting the matrices' dimensions to obtain 3D arrays of size (in your example) 51 × 1 × 5100 and 1 × 51 × 5100 respectively;
subtracting with implicit expansion, which gives an array of size 51 × 51 × 5100;
reshaping to collapse the first two dimensions into one, which gives the final 51*51 × 5100 matrix.
A = rand(51, 5100); % example matrix
B = rand(51, 5100); % example matrix, same number of columns
C = reshape(permute(A, [1 3 2]) - permute(B, [3 1 2]), [], size(A, 2));
The crux of the problem lies in getting the correct pairs of rows for both matrices. To do this, you could use the meshgrid() function to generate a matrix that varies from 1:n along its rows, and another that varies along its columns (where n is the number of rows).
For example:
mtx1 = reshape(1:9, 3, 3);
mtx2 = reshape(101:109, 3, 3);
n1 = size(mtx1, 1);
n2 = size(mtx2, 1);
[r1, r2] = meshgrid(1:n1, 1:n2);
This gives:
r1 =
1 2 3
1 2 3
1 2 3
r2 =
1 1 1
2 2 2
3 3 3
Next, flatten both r1 and r2:
f1 = r1(:)
f2 = r2(:)
Now, we have:
f1 =
1
1
1
2
2
2
3
3
3
f2 =
1
2
3
1
2
3
1
2
3
We can use f1 and f2 as the indices for our pairs of rows:
mtx1(f1, :) repeats the first row of mtx1 three times, then the second row, then the third row
mtx1(f1, :)
1 4 7
1 4 7
1 4 7
2 5 8
2 5 8
2 5 8
3 6 9
3 6 9
3 6 9
mtx2(f2, :) repeats the entire matrix mtx2 three times
mtx2(f2, :)
101 104 107
102 105 108
103 106 109
101 104 107
102 105 108
103 106 109
101 104 107
102 105 108
103 106 109
Subtract these two, and you get your pairwise difference of rows:
mtx2(f2, :) - mtx1(f1, :)
100 100 100
101 101 101
102 102 102
99 99 99
100 100 100
101 101 101
98 98 98
99 99 99
100 100 100
This also works when mtx1 and mtx2 have different row counts.
I would like to merge 2 vectors according their time values. This should look like this (column 1 = time, column 2 = actual value):
A =
1 234
3 121
4 456
6 6756
B =
2 435
5 90
10 365
Result:
C =
1 234
2 435
3 121
4 456
5 90
6 6756
10 365
Is there an elegant way to realize this in Matlab?
Here's an easy one-liner:
C = sortrows([A;B])
C =
1 234
2 435
3 121
4 456
5 90
6 6756
10 365
Note that this assumes that all of the time values in column 1 are unique. If this is not the case, you can use accumarray:
A =
1 234
3 121
4 456
6 6756
B =
2 435
5 90
10 365
B = [B; 1 512]
B =
2 435
5 90
10 365
1 512
C = [A;B];
D = accumarray(C(:,1),C(:,2));
U = unique(C(:,1));
E = [U,D(U)]
E =
1 746 %// 764 = 234 + 512
2 435
3 121
4 456
5 90
6 6756
10 365
First I would merge these matrices and then sort them by first column.
C = [A; B]
[Y, I] = sort(C(:,1))
C = C(I,:)
First you want to vertical concatenation:
A = [1 234; 3 121; 4 456; 6 6756];
B = [2 435; 5 90; 10 365];
C = vertcat(A,B)
Then you want to sort your answer based on the first column:
[~,inx]=sort(C(:,1));
out = C(inx,:);
>> out =
1 234
2 435
3 121
4 456
5 90
6 6756
10 365
So much more difficult than the 1 liner:
out = sortrows(C,1)
Why Matlab, why don't you have an option in sort to keep the index!
In the general case, you will need to do some form of concatenation and sorting. This is a one liner
C = sort([A,B],1);
So say I have two arrays:
A:14 63 13
38 44 23
11 12 13
38 44 23
B:38 44 23
I am trying to use ismember to return the index of every location where B is found in A. All examples I have found online only list the first or last occurrence of a match, I am trying to have a list indices for all values that match, even repeating ones. Thanks
Use ismember with the 'rows' arugment:
ismember(A, B, 'rows')
which results in a logical array [0 1 0 1] which is often better than an array of indices but if you want the indices specifically then just use find:
find(ismember(A,B,'rows'))
to return [2,4]
Note that this method will still work if B has multiple rows e.g. B = [38 44 23; 11 12 13], it will return [0; 1; 1; 1]
You can use bsxfun for the comarison:
idx = find( all( bsxfun(#eq, A, B), 2 )); %// only where all line matches
Results with
idx =
2
4
You can look into pdist2 if you have A and B as Nx3 sized arrays -
[indA,indB] = ind2sub([size(A,1) size(B,1)],find(pdist2(A,B)==0));
ind = [indA,indB]
Thus, in ind you would have the pairwise indices for the matches with the first column representing the indices for A and the second one for B.
Sample run -
A =
14 63 13
38 44 23
11 12 13
14 63 13
38 44 23
B =
38 44 23
14 63 13
ind =
2 1
5 1
1 2
4 2
This is just an improved version of shai's answer for handling multiple rows of B
idx = find(any(all( bsxfun(#eq, A, permute(B,[3 2 1])), 2 ),3));
Sample Run:
A = [14 63 13;
38 44 23;
11 12 13;
38 44 23];
B = [38 44 23;
11 12 13];
idx = find(any(all( bsxfun(#eq, A, permute(B,[3 2 1])), 2 ),3));
>> idx
idx =
2
3
4
I have the following matrix:
MatrixA =
1 10 50
23 45 76
71 81 91
1 2 3
4 5 6
78 89 91
2 3 4
I would like to run the var function for multiple ranges in each column. More specifically, I would like to calculate var for rows 1 through 3, 2 through 4, 3 through 5, etc. for each column. The output I would like would be:
1281.33 1260.33 430.33
1281.33 1564.33 2216.33
1566.33 2004.33 2496.33
... ... ...
I was thinking the syntax would be something along the lines of:
var(MatrixA([1 2 3]:[3 4 5],:))
but this (obviously) does not work.
I can do this using loops, but I was wondering if there is a solution to this that does not involve loops?
You can get rid of one loop using hankel function to create the ranges:
V = [];
for C = MatrixA,
V = [V, var(hankel(C(1:3),C(3:end))).'];
end
For instance if C contains the first column of MatrixA then
>> hankel(C(1:3),C(3:end))
ans =
1 23 71 1 4
23 71 1 4 78
71 1 4 78 2
and
>> var(hankel(C(1:3),C(3:end)))
ans =
1281.3 1281.3 1566.3 1902.3 1876
You could be a little creative with bsxfun and reshape to compute an index array and then compute the variances:
n = 3;
idx = bsxfun(#plus, 1:size(MatrixA, 1) - n + 1, (0:n - 1)');
B = reshape(var(reshape(MatrixA(idx, :), 3, [])), [], size(MatrixA, 2));
I am new in matlab and I am not familiar with array of matrices. I have a number of matrices nx6:
<26x6 double>
<21x6 double>
<27x6 double>
<36x6 double>
<29x6 double>
<30x6 double>
....
Each matrix is of this type:
>> Matrix{1,1}
A B C D E F
1 2 6 223 735064.287500000 F11
2 3 6 223 735064.288194445 F12
3 4 6 223 735064.288888889 F13
4 5 6 223 735064.290277778 F14
>> Matrix{2,1}
A B C D E F
1 2 6 223 735064.700694445 F21
2 3 6 223 735064.701388889 F22
3 4 6 223 735064.702083333 F23
4 5 6 223 735064.702777778 F24
>> Matrix{3,1}
A B C D E F
1 2 7 86 735064.3541666666 F31
2 3 7 86 735064.3548611112 F32
3 4 7 86 735064.3555555555 F33
4 5 7 86 735064.3562499999 F34
5 6 7 86 735064.702777778 F35
>> Matrix{4,1}
A B C D E F
1 2 7 86 735064.3569444444 F41
2 3 7 86 735064.3576388888 F42
3 4 7 86 735064.3583333333 F43
4 5 7 86 735064.3590277778 F44
5 6 6 86 735064.702777778 F45
Where E and F are dates in datenum format. Specifically F is the time difference.
Considering all matrices at once, I would like to sum the values of column F among all the matrices that have equal values in columns A, B, D.
For each value of the column D (the number of bus), I would like to obtain a new matrix like the following one:
A B C D H
1 2 6 223 F11+F21
2 3 6 223 F12+F22
3 4 6 223 F13+F23
4 5 6 223 F14+F24
A B C D H
1 2 7 86 F31+F41
2 3 7 86 F32+F42
3 4 7 86 F33+F43
4 5 7 86 F34+F44
5 6 7 86 F35+F45
Thank you in advance for you help!
This approach should get you started. I suggested setting up a matrix that stores the comparison between the columns 1,2 and 4. Based on that matrix you can then generate your output matrix. This saves you nested if statements and checks in your loop.
Here's an example (please note that I changed row 3 of Matrix{1,1}):
Matrix{1,1} = [ ...
1 2 6 223 735064.287500000 1;
2 3 6 223 735064.288194445 2;
3 4 6 223 735064.288888889 3;
4 5 6 223 735064.290277778 4];
Matrix{2,1} = [ ...
1 2 6 223 735064.700694445 10;
2 3 6 223 735064.701388889 10;
2 4 6 223 735064.702083333 10;
4 5 6 223 735064.702777778 10];
COMP = Matrix{1,1}(:,[1:2 4])==Matrix{2,1}(:,[1:2 4]);
a = 1;
for i=1:size(Matrix{1,1},1)
if sum(COMP(i,:)) == 3
SUM{1,1}(a,1:5) = Matrix{1,1}(i,1:5);
SUM{1,1}(a,6) = Matrix{1,1}(i,6) + Matrix{2,1}(i,6);
a = a + 1;
end
end
The matrix COMP stores a 1 for each element that is the same in Matrix{1,1} and Matrix{2,1} when comparing columns 1, 2 and 4.
This reduces the if-statement to a check if all elements in a row agree (hence sum == 3). If that condition is satisfied, a new matrix is generated (SUM{1,1}) which sums the entries in column 6, in this case:
SUM{1,1}(:,6) =
11
12
14