Checking a specific column in a matrix with a specific row,column in another matrix

Greetings,
I want to check an (entire column) of B with a specific (row,column) in A and then extract values in B that are lower/higher than that value in A. For example; B(:,1) with A(1,1). I have already done this by creating a function file and calling it in my script.
My question now is how do I go from B(:,1) with A(1,1) to B(:,2) with A(2,2) without using this.
[Higher, Lower] = check(A(1,1), B(:,1))
[Higher1, Lower1] = check(A(1,2), B(:,2))
I want something that will automatically insert the desired matrix position. I'm asking this because my actual data set for matrices A = 30*12 and B = 62*12, thus making my method below inefficient. I have also included the expected results below.
clc; clear;
A = [1 2 1 2 5 2 1 2; 3 4 5 6 7 8 2 1];
B = [1 2;0 1; 2 4; 3 7; 0 5; 1 3; 2 4; 3 3; 9 8];
% Check B with A (I HAVE PROBLEM WITH THIS)
[Higher, Lower] = check(A(1,1), B(:,1))
[Higher1, Lower1] = check(A(1,2), B(:,2))
My function file:
function [Higher, Lower] = check(x,y)
% This function checks the y against x and extracts the respective higher/lower values.
% Set initial count to 0
con1 = 0;
count1 = 0;
for j = 1
for i = 1:9
if y(i) > x(j)
con1 = con1 + 1;
Higher(con1,j) = y(i);
end
end
con1 = 0;
end
for j = 1
for i = 1:9
if y(i) < x(j)
count1 = count1 + 1;
Lower(count1,j) = y(i);
end
end
count1 = 0;
end
end
Expected results:
Higher = [2;3;2;3;9]
Lower = [0;0]
Higher1 = [4;7;5;3;4;3;8]
Lower1 = [1]
All help is greatly appreciated. Thanks.

1 Comment

Jan has already shown how to write a much simpler check function and you should use that. However, even if you were going to use a loop as you have done, never hardcode the bounds of the loops. You wrote a function that accept a x of any size, yet your loop assumes that x is 9 elements. The whole point of functions is that they adapt to the input, so just changing
for i = 1:9
to
for i = 1:numel(x)
would mean that your current code would work regardless of the size of x (instead of erroring if x has less than 9 elements and producing the wrong result if it has more).
Also,
for j = 1
Well, that's absurd, it's the same as
j = 1;

Sign in to comment.

 Accepted Answer

I've simplified the code at first:
A = [1 2 1 2 5 2 1 2; 3 4 5 6 7 8 2 1];
B = [1 2;0 1; 2 4; 3 7; 0 5; 1 3; 2 4; 3 3; 9 8];
[Higher, Lower] = check(A(1,1), B(:,1))
[Higher1, Lower1] = check(A(1,2), B(:,2))
function [Higher, Lower] = check(x,y)
% This function checks the y against x and extracts the respective higher/lower values.
Higher = y(y > x);
Lower = y(y < x);
end
This produces the wanted output. So what is the remaining problem? What does "how do I go from B(:,1) with A(1,1) to B(:,2) with A(2,2) without explicitly mentioning it" mean?
Maybe you want this:
A = rand(30, 12);
B = rand(62, 12);
Higher = cell(size(A));
Lower = cell(size(A));
for i1 = 1:size(A, 1)
for i2 = 1:size(A, 2)
[Higher{i1, i2}, Lower{i1, i2}] = check(A(i1, i2), B(:, i2));
end
end
I'm not sure, what the wanted output is. But for storing arrays of different sizes, cell arrays are perfect.

9 Comments

What I mean by "how do I go from B(:,1) with A(1,1) to B(:,2) with A(2,2) without explicitly mentioning it" is that I don't want to type these 2 lines of code:
[Higher, Lower] = check(A(1,1), B(:,1))
[Higher1, Lower1] = check(A(1,2), B(:,2))
I want something that will automatically put in the desired matrix position. Because my actual matrices are much larger. I have just simplified the matrices here to make it easier for me to digest the code.
As for your suggested code, I'm getting the following error:
Output argument "Lower" (and maybe others) not assigned during call to "check".
Error in test (line 21)
[Higher{i1, i2}, Lower{i1, i2}] = check(A(i1, i2), B(:, i2));
Thank you for your help.
Then please post, which code you are using for the function check. With this code, no errors occur:
function [Higher, Lower] = check(x,y)
Higher = y(y > x);
Lower = y(y < x);
end
The code you have posted in the original question fails, if there is no matching y element. Then Lower or Higher is not defined. My suggestion is faster and easier, so I suggest to use it.
Hello Jan,
I tried out your code and it does work for me. My next question is "I was wondering if it would be possible to simplify the code if I have multiple B data to check against A as I have 36 B data (B1-B36)" or do I just repeat the code like below?
A = rand(30, 12);
B1 = rand(62, 12);
B2 = rand(62, 12);
Higher55 = cell(size(A));
Lower55 = cell(size(A));
Higher56 = cell(size(A));
Lower56 = cell(size(A));
% Check begins
for i1 = 1:size(A, 1)
for i2 = 1:size(A, 2)
[Higher55{i1, i2}, Lower55{i1, i2}] = check1(A(i1, i2), B1(:, i2));
end
end
for i1 = 1:size(A, 1)
for i2 = 1:size(A, 2)
[Higher55{i1, i2}, Lower55{i1, i2}] = check1(A(i1, i2), B2(:, i2));
end
end
Thank you.
@Elizabeth: "does not work for me" is a lean description of the problem. I cannot guess, if you get an error message or if the result differ from your expectations. If you want some help from me, please do not let me guess, what the problems are. I cannot know, what the function check1() is.
It is a bad programming practice to hide indices in the names or variables. See TUTORIAL: How and why to avoid Eval (link). Instead of creating a bunch of variables with a "55" or "56" in the name, create a cell array instead and use the number as index: Higher{55}. This is what my code does already: I compares all elements of A with the columns of B and stores the resulting vectors in Lower and Higher.
If you really have "36 B data (B1-B36)", this is the problem. It would be much easier, if you store the input in an array: B{1} to B{36}.
Again: My code does not create Lower and Lower1 and so on, but the cell arrays Lower{1,1} and Lower{1,2} and so on, which contains te results for the comparison between A(1,1) and B(:,1) and between A(1,2) and B(:,2), etc.
It is not clear to me, what you want as output instead, e.g. for the mentioned "A = 30*12 and B = 62*12". My code creates Lower and Higher as {30 x 12} cell arrays. Creating 360 different variables would be a mess instead.
So please start with mentioning, what the problems with my code are, and post a meaningful example of what you want as output for a tiny input data set.
By the way, I'm confused. In the original question you asked:
" how do I go from B(:,1) with A(1,1) to B(:,2) with A(2,2) without using this"
Now the question contains
"multiple B data to check against A as I have 36 B data (B1-B36)"
Is this still the same problem?
Hi Jan,
My apologies for being confusing and thank you for your patience.
To clear things up, there are no errors with your code. My earlier problem was because I neglected to simplify my 'check' function file. After simplifying the check function as per your suggestion and using your suggested for loop code, no errors poped up and I was able to get the data that I desired.
Again, I'm really sorry about that.
For this:
By the way, I'm confused. In the original question you asked:
" how do I go from B(:,1) with A(1,1) to B(:,2) with A(2,2) without using this"
Now the question contains
"multiple B data to check against A as I have 36 B data (B1-B36)"
Is this still the same problem?
The "multiple B data to check against A as I have 36 B data (B1-B36)" is the second stage of this problem.
With your help, I was able solved the first part of the problem that is to "check 1 set of B data against A". Now, I was wondering if I could repeat it for multiple sets of B data. Do you think I should set up a different question for this second problem?
I have posted a simpler version of what I desire below.
% 1. Check if:
% ------------B(:,1) is larger than A(1,1) and extract that value.
% ------------B(:,1) is smaller than A(1,1) and extract that value.
% 2. Direction of check should proceed so on [B(:,2) with A(1,2)]...[B(:,n) with A(1,n)]
% Repeat 1 & 2 above for B1 data, B2 data until B36 data
A = [ 2 3 ; 4 5 ]; % A(2,2)
B = [ 1 0; 6 4; 5 5;]; % B(3,2)
B1 = [ 2 2; 0 5; 5 6;]; % B1(3,2)
B2 = [ 3 0; 6 5; 6 6;]; % B2(3,2)
% Results for B check against A:
Higher{1,1} = [6;5]; % B(:,1) is larger than A(1,1)
Higher{1,2} = [4;5]; % B(:,2) is larger than A(1,2)
Lower{1,1} = [1]; % B(:,1) is smaller than A(1,1)
Lower{1,2} = [0]; % B(:,2) is smaller than A(1,2)
% Results for B1 check against A:
higher{1,1} = [5]; % B1(:,1) is larger than A(1,1)
higher{1,2} = [5;6]; % B1(:,2) is larger than A(1,2)
lower{1,1} = [0]; % B1(:,1) is smaller than A(1,1)
lower{1,2} = [2]; % B1(:,2) is smaller than A(1,2)
% "Current Code" for B check against A only:
Higher = cell(size(A));
Lower = cell(size(A));
for i1 = 1:size(A, 1)
for i2 = 1:size(A, 2)
[Higher{i1, i2}, Lower{i1, i2}] = check(A(i1, i2), B(:, i2));
end
end
% "Current Code" for B1 check against A only:
higher = cell(size(A));
lower = cell(size(A));
for i1 = 1:size(A, 1)
for i2 = 1:size(A, 2)
[higher{i1, i2}, lower{i1, i2}] = check(A(i1, i2), B1(:, i2));
end
end
% Where function check is defined below:
function [Higher, Lower] = check(x,y)
Higher = y(y > x);
Lower = y(y < x);
end
% Modify above "Current code" to check multiple sets of B data against A
Thank you for your help. I really appreciate you taking the time and effort to help me.
As Jan said, never ever create numbered variables. Yes, if you have variables B1, B2, etc., you'll be forced to copy/paste the same lines of code (or use slow buggy workarounds that I won't even mention). Store all these B as elements of an array/cell array and you can let the computer do the repetitive work for you.
Jan has already shown you how to do that.
B = {[ 1 0; 6 4; 5 5;], ...your original B
[ 2 2; 0 5; 5 6;], ...your B1
[ 3 0; 6 5; 6 6;]}; %your B2
Higher = cell(size(B));
Lower = cell(size(B));
for bidx = 1:numel(B)
[Higher{bidx}, Lower{bidx}] = check(A, B{bidx});
end
Note that if all the B{i} are all the same size, you could use a 3D matrix instead which would remove the need for the loop entirely.
@ Guillaume, I inserted the B data into an array but am getting the following error.
Error in check (line 4)
Higher = y(y > x);
Error in test (line 12)
[Higher{bidx}, Lower{bidx}] = check(A, B{bidx});
Do you know what's causing this error?
@Elizabeth: This is not the complete message. The part, which mentions what the problem is, is missing.
I guess that now either A is the complete matrix, or B contains something other than mentioned before. Note that in all othercode before, check was called with 1 element of A only, A(i1,i2), but now you provide the complete matrix.
@Jan @Guillaume
I have managed to solve the issue. Thank you both for your help.

Sign in to comment.

More Answers (0)

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Asked:

on 28 Mar 2019

Edited:

Jan
on 29 Mar 2019

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!