How to remove all the rows from a matrix that match values in another vector? - matlab

I am making an exclude vector, so that the rows containing any value present in the second column of the matrix user from the exclude list are removed. How do I do that efficiently, without using a for loop to iterate through user for each item in exclude one by one?
My code below does not work:
count=0;
% Just showing how I am constructing `exclude`, to show that it can be long.
% So, manually removing each item from `exclude` is not an option.
% And using a for loop to iterate through each element in `exclude` can be inefficient.
for b=1:size(user_cat,1)
if user_cat(b,4)==0
count=count+1;
exclude(count,1) = user_cat(b,1);
end
end
% This is the important line of focus. You can ignore the previous parts.
user = user(user(:,2)~=exclude(:),:);
The last line gives the following error:
Error using ~=
Matrix dimensions must agree.
So, I am having to use this instead:
for b=1:size(exclude,1)
user = user(user(:,2)~=exclude(b,1),:);
end
Example:
user=[1433100000.00000 26 620260 7 1433100000000.00 0 0 2 1 100880 290 23
1433100000.00000 26 620260 7 1433100000000.00 0 0 2 1 100880 290 23
1433100000.00000 25 620160 7 1433100000000.00 0 0 2 1 100880 7274 22
1433100000.00000 21 619910 7 1433100000000.00 24.1190000000000 120.670000000000 2 0 100880 53871 21
1433100000.00000 19 620040 7 1433100000000.00 24.1190000000000 120.670000000000 2 0 100880 22466 21
1433100000.00000 28 619030 7 1433100000000.00 24.6200000000000 120.810000000000 2 0 100880 179960 16
1433100000.00000 28 619630 7 1433100000000.00 24.6200000000000 120.810000000000 2 0 100880 88510 16
1433100000.00000 28 619790 7 1433100000000.00 24.6200000000000 120.810000000000 2 0 100880 12696 16
1433100000.00000 7 36582000 7 1433100000000.00 0 0 2 0 100880 33677 14
1433000000.00000 24 620010 7 1433000000000.00 0 0 2 1 100880 3465 14
1433000000.00000 4 36581000 7 1433000000000.00 0 0 2 0 100880 27809 12
1433000000.00000 20 619960 7 1433000000000.00 0 0 2 1 100880 860 11
1433000000.00000 30 619760 7 1433000000000.00 25.0060000000000 121.510000000000 2 0 100880 34706 10
1433000000.00000 33 619910 7 1433000000000.00 0 0 2 0 100880 15060 9
1433000000.00000 26 619740 6 1433000000000.00 0 0 2 0 100880 52514 8
1433000000.00000 18 619900 6 1433000000000.00 0 0 2 0 100880 21696 8
1433000000.00000 16 619850 6 1433000000000.00 24.9910000000000 121.470000000000 2 0 100880 10505 1
1433000000.00000 16 619880 6 1433000000000.00 24.9910000000000 121.470000000000 2 0 100880 1153 1
1433000000.00000 28 619120 6 1433000000000.00 0 0 2 0 100880 103980 24
1433000000.00000 21 619870 6 1433000000000.00 0 0 2 0 100880 1442 24];
exclude=[ 3
4
7
10
17
18
19
28
30
33 ];
Desired output:
1433100000.00000 26 620260 7 1433100000000.00 0 0 2 1 100880 290 23
1433100000.00000 26 620260 7 1433100000000.00 0 0 2 1 100880 290 23
1433100000.00000 25 620160 7 1433100000000.00 0 0 2 1 100880 7274 22
1433100000.00000 21 619910 7 1433100000000.00 24.1190000000000 120.670000000000 2 0 100880 53871 21
1433000000.00000 24 620010 7 1433000000000.00 0 0 2 1 100880 3465 14
1433000000.00000 20 619960 7 1433000000000.00 0 0 2 1 100880 860 11
1433000000.00000 26 619740 6 1433000000000.00 0 0 2 0 100880 52514 8
1433000000.00000 16 619850 6 1433000000000.00 24.9910000000000 121.470000000000 2 0 100880 10505 1
1433000000.00000 16 619880 6 1433000000000.00 24.9910000000000 121.470000000000 2 0 100880 1153 1
1433000000.00000 21 619870 6 1433000000000.00 0 0 2 0 100880 1442 24

Use ismember to find the indices of the second column of user where elements of exclude exist to get the indices of the rows to be removed. Negate these row indices to get the row indices to be kept and use matrix indexing to keep these rows.
user = user(~ismember(user(:,2),exclude),:);

Related

My for loop won't output anything (Matlab)

I'm trying to get this for loop to work on Matlab so I can plot these three histograms. I'm guessing it won't output because it says that my variables such as a_M_S1 keep changing size on every loop iteration, so the process is essentially inefficient. Any help? Below is the code.
I'm basically trying to generate 500 samples of 100 readings so I can then plot a histogram using estimated parameter values.
clear
clc
% Importing Data
%a = 0.9575
for m=1:500
seed=m;
rng(seed);
syms x
F=((1/atanh(0.9575))*((0.9575^(2*x-1))/(2*x-1)));
for n=1:100
data_1(n)=ceil(vpasolve(F==rand(1)));
end
Data_1(m,:)=data_1;
end
clear
clc
Data_1=[49 1 3 17 13 3 5 51 7 1
9 3 67 1 3 1 1 1 1 99
5 13 21 17 41 1 1 9 23 1
1 5 1 1 41 1 13 1 5 27
5 37 99 1 1 33 1 1 9 1
1 3 47 11 7 1 1 41 21 27
5 1 1 11 45 7 3 5 1 17
13 5 3 3 1 99 1 59 1 13
3 5 1 35 1 1 1 1 5 19
5 1 1 1 79 3 1 1 1 1
31 3 1 1 1 21 69 39 1 29
3 3 1 1 5 1 3 1 1 15
1 1 9 1 7 1 1 1 1 11
27 9 1 3 39 5 1 5 7 1
1 1 7 5 1 1 3 1 3 23
5 1 21 1 1 7 1 17 1 3
11 11 5 1 9 1 1 1 1 37
33 1 9 7 1 1 31 27 1 1
5 5 1 17 3 31 1 45 37 1
1 1 19 47 9 7 5 1 9 1
11 1 61 5 29 1 95 1 1 1
13 19 1 1 13 1 23 7 73 1
1 1 11 1 5 1 3 1 7 1
15 1 9 53 3 7 3 21 7 3
1 7 1 1 23 7 5 1 3 1
1 7 1 3 1 1 1 7 3 5
1 1 1 43 7 3 1 1 21 5
1 39 1 5 13 3 1 5 1 3
1 11 1 1 29 17 25 1 9 1
17 9 13 11 1 5 29 3 3 1
65 5 63 1 1 3 5 1 7 1
21 3 7 1 1 1 27 11 15 3
1 1 1 1 21 1 5 3 1 11
5 1 3 7 1 5 43 5 7 75
29 7 83 1 3 5 15 1 1 3
1 1 9 1 13 1 17 23 1 5
99 1 1 1 5 7 9 3 7 1
1 11 1 11 21 1 5 9 5 1
33 49 3 9 15 1 1 5 1 1
1 17 1 1 1 1 13 1 1 9
5 13 1 1 5 3 1 1 67 1
5 1 1 1 7 27 1 21 47 1
1 1 1 21 3 17 1 5 5 1
1 1 17 29 99 1 9 1 5 15
17 5 1 13 1 1 1 1 1 21
1 21 1 1 1 11 9 35 31 15
99 15 1 1 9 3 1 21 1 1
1 1 9 33 1 1 31 9 29 47
41 99 1 7 17 5 9 3 3 13
1 29 9 5 11 1 1 7 37 15];
Data_2=[1 1 3 3 5 7 1 3 1 1
1 1 1 1 1 1 1 1 1 13
5 1 5 1 1 1 1 3 1 1
1 1 3 1 1 1 1 3 1 1
1 1 13 5 1 3 1 1 5 1
3 3 1 7 3 5 3 1 3 1
1 1 1 1 1 3 3 5 1 1
1 1 1 9 1 1 1 1 5 1
1 1 1 1 1 11 7 1 5 1
17 1 1 7 3 7 3 5 5 1];
for o=1:500
syms a
%Method of Moments (MM)
mean_S1 = mean(transpose(Data_1(o,:)));
a_MM_S1(o) = vpa(vpasolve((a)/((atanh(a))*(1-a.^2)) == mean_S1,a),4);
mean_S2 = mean(transpose(Data_2(o,:)));
a_MM_S2(o) = vpa(vpasolve((a)/((atanh(a))*(1-a.^2)) == mean_S2,a),4);
%Using Lower Quantile (OS)
lower_S1 = floor(quantile(Data_1(o,:),0.25));
a_LQ_S1(o) = vpa(vpasolve((a)/(atanh(a)) == 0.25,a),4);
lower_S2 = floor(quantile(Data_2(o,:),0.25));
a_LQ_S2(o) = vpa(vpasolve((a)/(atanh(a)) == 0.25,a),4);
%Using Median (OSM)
median_S1 = floor(quantile(Data_1(o,:),0.5));
a_M_S1(o) = vpa(vpasolve((a)/(atanh(a)) == 0.5,a),4);
median_S2 = floor(quantile(Data_2(o,:),0.5));
a_M_S2(o) = vpa(vpasolve((a)/(atanh(a)) == 0.5,a),4);
end
a_MM_S1=transpose(a_MM_S1);
a_LQ_S1=transpose(a_LQ_S1);
a_M_S1=transpose(a_M_S1);
a_MM_S2=transpose(a_MM_S2);
a_LQ_S2=transpose(a_LQ_S2);
a_M_S2=transpose(a_M_S2);
figure(1)
histogram([double(a_MM_S1),double(a_MM_S2)],20),title('Method of Moments')
figure(2)
histogram([double(a_LQ_S1),double(a_LQ_S2)],20),title('Using Lower Quartile as Estimator')
figure(3)
histogram([double(a_M_S1),double(a_M_S2)],20),title('Using Median as Estimator')

How to get list of neighbors with distance N from index in matrix? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I have a matrix like this:
35 1 6 26 19 24
3 32 7 21 23 25
31 9 2 22 27 20
8 28 33 17 10 15
30 5 34 12 14 16
4 36 29 13 18 11
I want a list of neighbors with distance 3 for each cell. For example,
the list of neighbors with distance 3 for (1, 1) is:
[8, 28, 33, 17, 26, 21, 22, 17]
Visual explanation:
[35] 1 6 |26| 19 24
3 32 7 |21| 23 25
31 9 2 |22| 27 20
-------------------
8 28 33 |17| 10 15
-------------------
30 5 34 12 14 16
4 36 29 13 18 11
The list of neighbors with distance 3 for (3, 3) is
[4, 36, 29, 13, 18, 11, 24, 25, 20, 15, 16]
Visual explanation:
35 1 6 26 19 |24|
3 32 7 21 23 |25|
31 9 [2] 22 27 |20|
8 28 33 17 10 |15|
30 5 34 12 14 |16|
------------------------
4 36 29 13 18 |11|
------------------------
Generate an all-zero "index matrix" idx with the same size of your matrix A, and set the "seed" to 1:
A = [ ...
35 1 6 26 19 24; ...
3 32 7 21 23 25; ...
31 9 2 22 27 20; ...
8 28 33 17 10 15; ...
30 5 34 12 14 16; ...
4 36 29 13 18 11 ...
]
idx = zeros(size(A));
idx(3, 2) = 1
We get:
A =
[...]
idx =
0 0 0 0 0 0
0 0 0 0 0 0
0 1 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
Now, we use 2-D convolution, i.e. MATLAB's conv2 method to create the correct index matrix w.r.t. to the distance d:
idx = logical(conv2(idx, ones(2*d+1), 'same') - conv2(idx, ones(2*d-1), 'same'))
(Convolution is the key to success.)
Then, we get:
idx =
0 0 0 0 1 0
0 0 0 0 1 0
0 0 0 0 1 0
0 0 0 0 1 0
0 0 0 0 1 0
1 1 1 1 1 0
Since we already casted the indices to logical, we can directly access the proper elements in the matrix A:
B = A(idx).'
The final result:
B =
4 36 29 13 19 23 27 10 14 18
Please notice the difference in the result as you wrote (3, 2) in your second example, but actually marked (3, 3) as "seed".
Hope that helps!
Disclaimer: Tested with Octave 5.1.0, but also works with MATLAB Online.

How can I make a diamond of zeroes in a matrix of any size? [closed]

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

(matlab) qtdecomp works with uint8 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.

Value comparison of matrix elements in MATLAB

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