Say I have a 256 by 256 matrix. I would like to replace any values that are 'greater' or 'equal' to 10 with 1 and make the rest 0 i.e. (values < 10).
For example,
2 3 6 15 24 32 1 7 39 10 ....
1 5 7 11 19 10 20 28 9 ........
10 24 6 29 10 25 32 10 ..........
.................................
.................................
and I want the output to be:
0 0 0 1 1 1 0 0 1 1 ............
0 0 0 1 1 1 1 1 0 ..............
1 1 0 1 1 1 1 1 ................
................................
................................
How can I do it?
Example:
a = [3 2 6 6 ;
7 5 3 7 ;
7 10 8 9 ;
2 4 3 10];
b = ( a > 5 )
b =
0 0 1 1
1 0 0 1
1 1 1 1
0 0 0 1
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have a square Matrix N x M, odd dimensions, and I want to put a diamond of zeroes, for example, for a 5 x 5 matrix:
1 3 2 4 2
5 7 8 9 5
3 2 4 6 3
6 8 2 1 3
3 3 3 3 3
Is transform to:
1 3 0 4 2
5 0 8 0 5
0 2 4 6 0
6 0 2 0 3
3 3 0 3 3
How can this be done efficiently?
I'll bite, here is one approach:
% NxN matrix
N = 5;
assert(N>1 && mod(N,2)==1);
A = magic(N);
% diamond mask
N2 = fix(N/2);
[I,J] = meshgrid(-N2:N2);
mask = (abs(I) + abs(J)) == N2;
% fill with zeros
A(mask) = 0;
The result:
>> A
A =
17 24 0 8 15
23 0 7 0 16
0 6 13 20 0
10 0 19 0 3
11 18 0 2 9
I also had some time to play around. For my solution there are no limits concerning A being odd or even or larger than 1. Every integer is fine (even 0 works, though it does not make sense).
% NxN matrix
N = 7;
A = magic(N);
half = ceil( N/2 );
mask = ones( half );
mask( 1 : half+1 : half*half ) = 0;
mask = [ fliplr( mask ) mask ];
mask = [ mask; flipud( mask ) ];
if( mod(N,2) == 1 )
mask(half, :) = []
mask(:, half) = []
end
A( ~mask ) = 0;
A
I am first creating a square sub-matrix mask of "quarter" size (half the number of columns and half the number of rows, ceil() to get one more in the case N is odd).
Example for N=7 -> half=4.
mask =
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
I then set it's diagonal values to zero:
mask =
0 1 1 1
1 0 1 1
1 1 0 1
1 1 1 0
Mirror the mask horizontally:
mask =
1 1 1 0 0 1 1 1
1 1 0 1 1 0 1 1
1 0 1 1 1 1 0 1
0 1 1 1 1 1 1 0
Then mirror it vertically:
mask =
1 1 1 0 0 1 1 1
1 1 0 1 1 0 1 1
1 0 1 1 1 1 0 1
0 1 1 1 1 1 1 0
0 1 1 1 1 1 1 0
1 0 1 1 1 1 0 1
1 1 0 1 1 0 1 1
1 1 1 0 0 1 1 1
As N is odd we got a redundant row and redundant column that are then removed:
mask =
1 1 1 0 1 1 1
1 1 0 1 0 1 1
1 0 1 1 1 0 1
0 1 1 1 1 1 0
1 0 1 1 1 0 1
1 1 0 1 0 1 1
1 1 1 0 1 1 1
The logical not is then used as a mask to select the values in the original matrix that are set to 0.
Probably not as efficient as #Amro's solution, but it works. :D
My solution:
looking at the first left half of the matrix
in the first row 0 is in the middle column (let's call it mc)
in the second row the 0is in column mc-1
and so on while the rows increase
when you reach column 1 the sequence continue but with mc+1 but the rows decrease
In a similar way for the right half of the matrix
n=7
a=randi([20 30],n,n)
% Centre of the matrix
p=ceil(n/2)
% Identify the column sequence
col=[p:-1:1 2:p p+1:n n-1:-1:p]
% Identify the row sequence
row=[1:n n-1:-1:1]
% Transorm the row and column index in linear index
idx=sub2ind(size(a),row,col)
% Set the 0'
a(idx)=0
a =
22 29 23 27 27 21 23
29 29 21 27 24 26 24
30 28 21 27 29 28 25
28 22 24 20 27 24 25
23 26 21 20 30 20 29
26 20 26 23 25 22 25
21 24 25 25 23 21 30
a =
22 29 23 0 27 21 23
29 29 0 27 0 26 24
30 0 21 27 29 0 25
0 22 24 20 27 24 0
23 0 21 20 30 0 29
26 20 0 23 0 22 25
21 24 25 0 23 21 30
Hope this helps.
Qapla'
Using indexing (only works when N is odd):
N = 7;
% Random matrix
A = randi(100, N);
idx = [N-1:-2:1; 2:2:N];
A(cumsum([ceil(N/2) idx(:)' idx(end-1:-1:1)])) = 0
A =
60 77 74 0 54 83 9
8 48 0 76 0 28 67
6 0 32 78 83 0 10
0 27 25 5 11 39 0
76 0 49 43 67 0 16
79 7 0 86 0 70 78
57 28 85 0 81 44 81
Is there a way to find the maximum flow between each pair of vertices in matlab?
c = sparse([1 1 2 2 3 4 4 5 5 6 7 8 9 9],[2 3 3 4 5 6 7 6 7 8 9 10 8 10],[15 10 3 8 9 7 5 6 2 12 10 6 10 8],10,10)
a = [2 3 4 5 6 7 8 9 10]
b = arrayfun(#(x)max_flow(c,1,x),a)
OR
b = arrayfun(#(x)graphmaxflow(c,1,x),a)
b =
15 13 8 9 13 7 16 7 13
So, I can take a sparse matrix and get the maximum flow from one vertex to all others. Is there a way to continue this to obtain the max flow for all of the pairs?
I'd eventually like to be able to find the all-pair max flow for a directed, weighted graph. . .
Got it to work:
c = sparse([1 1 2 2 3 4 4 5 5 6 7 8 9 9],[2 3 3 4 5 6 7 6 7 8 9 10 8 10],[15 10 3 8 9 7 5 6 2 12 10 6 10 8],10,10)
for a=1:10
for b=1:10
if a==b
continue
end
t(b,a)=graphmaxflow(c,a,b);
p=t(:);
end
end
I couldn't figure out a way to use arrayfun to do this.
Each maximum flow value:
t =
0 0 0 0 0 0 0 0 0 0
15 0 0 0 0 0 0 0 0 0
13 3 0 0 0 0 0 0 0 0
8 8 0 0 0 0 0 0 0 0
9 3 9 0 0 0 0 0 0 0
13 10 6 7 6 0 0 0 0 0
7 7 2 5 2 0 0 0 0 0
16 11 8 12 8 12 10 0 10 0
7 7 2 5 2 0 10 0 0 0
13 11 8 11 8 6 10 6 14 0
p =
0
15
13
8
9
13
7
...
i have below .dat file, i want matlab reads data in the 'REQUESTS/DURATIONS:' part and save them in a single matrix in size (32,7). i don't know which function to use ,i don't know how to do it. please help me.
file with basedata : j30_17.bas
initial value random generator: 79602564
projects : 1
jobs (incl. supersource/sink ): 32
horizon : 141
RESOURCES
- renewable : 4 R
- nonrenewable : 0 N
- doubly constrained : 0 D
REQUESTS/DURATIONS:
jobnr. mode duration R 1 R 2 R 3 R 4
------------------------------------------------------------------------
1 1 0 0 0 0 0
2 1 1 0 0 0 5
3 1 1 0 3 0 0
4 1 1 8 0 0 0
5 1 7 0 0 2 0
6 1 6 0 0 0 3
7 1 4 1 0 0 0
8 1 5 0 0 10 0
9 1 8 0 0 3 0
10 1 7 0 0 0 1
11 1 8 9 0 0 0
12 1 1 7 0 0 0
13 1 2 0 3 0 0
14 1 3 0 0 0 6
15 1 10 0 7 0 0
16 1 10 3 0 0 0
17 1 2 0 0 3 0
18 1 10 0 0 4 0
19 1 1 0 0 0 3
20 1 1 0 0 7 0
21 1 7 0 2 0 0
22 1 9 0 0 0 10
23 1 9 0 0 7 0
24 1 4 0 4 0 0
25 1 4 0 3 0 0
26 1 1 0 0 4 0
27 1 1 9 0 0 0
28 1 8 0 0 0 9
29 1 1 0 0 0 1
30 1 2 0 8 0 0
31 1 7 0 4 0 0
32 1 0 0 0 0 0
************************************************************************
RESOURCEAVAILABILITIES:
R 1 R 2 R 3 R 4
10 8 13 12
************************************************************************
If you skip the header, textscan() will stop reading the file once the actual type of data does not correspond to the one specified in format, i.e. when all those asterisks begin:
fid = fopen('C:\...\test.txt');
data = textscan(fid, '%f%f%f%f%f%f%f','HeaderLines',15);
fclose(fid);
I'm not sure about older versions, but 2013a can import text files by right clicking a file under the "Current Folder" panel and selecting "Import Data...". The import wizard will open up and allow you to select the range of data to import. Select the matrix option, and click "Import Selection."
To save your matrix, just use the save command.
This approach works well for single files that you just need to read quickly, but not for a large repetetive task.
In matlab, if you have a matrix A you can find the matrix B containing all of the unique rows of A as follows:
B = unique(A,'rows');
What I have is a 3d matrix, with rows and columns as the first two dimensions, and one additional dimension ('slices').
How can I get the 3d matrix containing all the unique slices in a matrix A? Here's an example of the kind of functionality I want:
>> A % print out A
A(:,:,1) =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
A(:,:,2) =
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
A(:,:,3) =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
A(:,:,4) =
0 0 0 1
0 0 1 0
0 1 0 0
1 0 0 0
>> unique(A,'slices'); % get unique slices
A(:,:,1) =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
A(:,:,2) =
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
A(:,:,3) =
0 0 0 1
0 0 1 0
0 1 0 0
1 0 0 0
I would begin by reshaping A so each slice becomes a row (with the reshape command). Then use unique(A, 'rows'). Finally, reshape the unique rows back to the same shape the slices.
For example:
% transforming so each row is a slice in row form
reshaped_A = reshape(A, [], size(A, 3))';
% getting unique rows
unique_rows = unique(reshaped_A, 'rows');
% reshaping back
unique_slices = reshape(unique_rows', size(A, 1), size(A, 2), []);
Or all in one line:
reshape(unique(reshape(A, [], size(A, 3))', 'rows')', size(A, 1), size(A, 2), [])
I haven't checked this above code so use with caution! But it should give the idea.
EDIT
Here it is working on your data (also fixed little bug in above code):
>> reshaped_A = reshape(A, [], size(A, 3))'
reshaped_A =
Columns 1 through 11
16 5 9 4 2 11 7 14 3 10 6
1 0 0 0 0 1 0 0 0 0 1
16 5 9 4 2 11 7 14 3 10 6
0 0 0 1 0 0 1 0 0 1 0
Columns 12 through 16
15 13 8 12 1
0 0 0 0 1
15 13 8 12 1
0 1 0 0 0
Each of these ^^ rows is one of the original slices
>> unique_rows = unique(reshaped_A, 'rows')
unique_rows =
Columns 1 through 11
0 0 0 1 0 0 1 0 0 1 0
1 0 0 0 0 1 0 0 0 0 1
16 5 9 4 2 11 7 14 3 10 6
Columns 12 through 16
0 1 0 0 0
0 0 0 0 1
15 13 8 12 1
These ^^ are the unique slices, but in the wrong shape.
>> unique_slices = reshape(unique_rows', size(A, 1), size(A, 2), [])
unique_slices(:,:,1) =
0 0 0 1
0 0 1 0
0 1 0 0
1 0 0 0
unique_slices(:,:,2) =
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
unique_slices(:,:,3) =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
A very simple and scalable solution would be:
A = cat(3, [16 2 3 13;5 11 10 8;9 7 6 12;4 14 15 1], [1 0 0 0;0 1 0 0;0 0 1 0;0 0 0 1], [16 2 3 13;5 11 10 8;9 7 6 12;4 14 15 1], [0 0 0 1;0 0 1 0;0 1 0 0;1 0 0 0])
[n,m,p] = size(A);
a = reshape(A,n,[],1);
b = reshape(a(:),n*m,[])';
c = unique(b,'rows', 'stable')'; %If the 'stable' option is supported by your version.
%If the 'stable' option is not supported, but it's still required, use the index vector option, as required.
%i.e.,
%[c,I,J] = unique(b,'rows');
unique_A = reshape(c,n,m,[])
Results:
A(:,:,1) =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
A(:,:,2) =
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
A(:,:,3) =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
A(:,:,4) =
0 0 0 1
0 0 1 0
0 1 0 0
1 0 0 0
unique_A(:,:,1) =
0 0 0 1
0 0 1 0
0 1 0 0
1 0 0 0
unique_A(:,:,2) =
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
unique_A(:,:,3) =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
Source: How to find unique pages in a 3d matrix?
I haven't fully understood how qtdecomp works...
I = [1 1 1 1 2 3 6 6
1 1 2 1 4 5 6 8
1 1 1 1 10 15 7 7
1 1 1 1 20 25 7 7
20 22 20 22 1 2 3 4
20 22 22 20 5 6 7 8
20 22 20 20 9 10 11 12
22 22 20 20 13 14 15 16];
S = qtdecomp(I,2);
disp(full(S));
The results of this are:
4 0 0 0 1 1 2 0
0 0 0 0 1 1 0 0
0 0 0 0 1 1 2 0
0 0 0 0 1 1 0 0
4 0 0 0 1 1 1 1
0 0 0 0 1 1 1 1
0 0 0 0 1 1 1 1
0 0 0 0 1 1 1 1
in the left bottom 4*4 matrix, maximum value (22) of the block elements minus the minimum value (20) is 2, so when decomposing this part, it will left as is.
When I do this on a uint8 matrix:
I = uint8([...
1 1 1 1 2 3 6 6
1 1 2 1 4 5 6 8
1 1 1 1 10 15 7 7
1 1 1 1 20 25 7 7
20 22 20 22 1 2 3 4
20 22 22 20 5 6 7 8
20 22 20 20 9 10 11 12
22 22 20 20 13 14 15 16]);
S = qtdecomp(I,2/255);
disp(full(S));
the answer is just like before. But when I change S to this:
S = qtdecomp(I,1.9/255);
The answer is
4 0 0 0 1 1 2 0
0 0 0 0 1 1 0 0
0 0 0 0 1 1 2 0
0 0 0 0 1 1 0 0
4 0 0 0 1 1 1 1
0 0 0 0 1 1 1 1
0 0 0 0 1 1 1 1
0 0 0 0 1 1 1 1
I suppose the left bottom 4*4 matrix should decompose, but why doesn't it?
What matlab does here is when I is uint8 it multiples the threshold by 255 and rounds it, so 1.9/255 is evaluated to 2.
You can see this by opening the source code for qtdecomp (by pressing ctrl+D) or here. There's an if/elseif near the end of the file (params{1} = round(255 * params{1});).
You should be able to use S = qtdecomp(I,1/255); to get the result you are looking for.