MATLAB Logical Indexing Greg Reese, Ph.D Research Computing Support Group Academic Technology Services Miami University MATLAB Logical Indexing © 2010-2013 Greg Reese. All rights reserved 2 Logical indexing One method of selecting elements in a matrix or vector is to choose those that meet some criterion, e.g., – the elements that are greater than zero – the elements that are not more than three standard deviations from the mean MATLAB does this by logical indexing and relational operators 3 Logical indexing MATLAB has the usual relational operators Symbol == ~= < > <= >= Operation Equal Not equal Less than Greater than Less than or equal Greater than or equal To get more information, type help ops 4 Logical indexing The result of comparing two scalars with a relational operator is a logical value. A logical value can only be true or false MATLAB represents true by the number 1 and false by 0 • Can also use the keywords true and false 5 Logical indexing Example >> x=5; >> x>5 ans = 0 >> x<=5 ans = 1 >> x==5 ans = 1 >> x~=5 ans = 0 6 Logical indexing When compare vector to vector, or vector to scalar, MATLAB • Does elementwise comparison – Compares scalar to every element of vector – Compares corresponding elements of vectors • Vectors must be same dimension • Result is vector of logical values • Result has same dimension as vector in comparison 7 Logical indexing Example >> x=8:12 x = >> x>10 ans = >> x==11 ans = >> x>=7 ans = 8 9 10 11 12 0 0 0 1 1 0 0 0 1 0 1 1 1 1 1 8 Logical indexing Tip It helps to picture in your mind that the result of a logical comparison 1. Is a vector 2. Has a 0 or 1 corresponding to each original element >> x=8:12 x = 8 >> x>10 ans = 0 9 10 11 12 0 0 1 1 9 Logical indexing Try It >> times = [ 9.7 9.9 10.1 12.8 ]; Mark times less than nine >> times < 9 ans = 0 0 0 0 Mark times greater than 12 >> times > 12 ans = 0 0 0 1 Mark times equal to 9.9 >> times == 9.9 ans = 0 1 0 0 ==, not = 10 Logical indexing MATLAB provides logical operations such as AND, OR, NOT, etc. • Can compare two scalars • If compare scalar to vector or vector to vector, do elementwise comparison – If two vectors, must both be same dimension To get more information, type help ops 11 Logical indexing Symbol & | xor() ~ any() all() Operation AND – true if both elements are nonzero, false otherwise OR – true if one or both elements are nonzero, false otherwise EXCLUSIVE OR – true if exactly one element is nonzero, false otherwise NOT – makes nonzero element zero and zero element one True if any element of a vector is nonzero, false otherwise True if all elements of a vector are nonzero, false otherwise 12 Logical indexing Example Child – 12 or less years Teenager – more than 12 and less than 20 years Adult – 20 or more years >> age=[45 47 15 13 11] age = 45 47 15 13 11 13 Logical indexing Example age = 45 47 Who is a teenager? >> age>=13 ans = 1 1 >> age<=19 ans = 0 0 >> age>=13 & age<=19 ans = 0 0 15 13 11 1 1 0 1 1 1 1 1 0 14 Logical indexing Example >> age=[45 47 15 13 11] age = 45 47 15 13 11 0 1 0 1 Who is not a teenager? >> ~(age>=13 & age<=19) ans = 1 1 0 Who is an adult or a child? >> age>19 | age<13 ans = 1 1 0 15 Logical indexing Example >> age=[45 47 15 13 11] age = 45 47 15 13 11 Are there any teenagers? >> any( age >= 13 & age <= 19 ) ans = 1 Are all the people teenagers? >> all( age >= 13 & age <= 19 ) ans = 0 16 Logical indexing For even more power you can use logical values as subscripts in a vector or matrix. This is called logical indexing or logical subscripting. To perform logical subscripting on a vector x, pass it (in parentheses) a logical vector of the same dimension. The result is a vector of all the elements of x for which the logical vector is true. 17 Logical indexing Example >> numbers = 1:8 numbers = 1 2 3 4 5 6 7 8 % find even numbers greater than 4 >> matches = ... rem( numbers, 2 ) == 0 & numbers > 4 matches = 0 0 0 0 0 1 0 1 >> numbers(matches) ans = 6 8 18 Logical indexing Example numbers = 1 2 3 4 5 6 7 8 matches = 0 0 0 0 0 1 0 1 Think of numbers(matches) as pulling out of numbers all elements that have a 1 in the corresponding element of matches numbers = 1 2 3 4 5 6 7 8 matches = 0 0 0 0 0 1 0 1 >> numbers(matches) ans = 6 8 19 Logical indexing Try It >> age=[45 47 15 13 11] age = 45 47 15 13 11 Mark teenagers with 1, non-teens with 0 >> age>=13 & age<=19 ans = 0 0 1 1 0 How old are the teenagers? >> age( age >= 13 & age <= 19) ans = 15 13 20 Logical indexing Tip If you’re going to use the results of a calculation a lot, compute it once and save it in a variable. 21 Logical indexing Example >> age=[45 47 15 13 11]; >> weight=[202 151 113 125 94]; >> teenager = age>=13 & age<=19; >> age(teenager) ans = 15 13 >> weight(teenager) ans = 113 125 22 Logical indexing Tip Since relational and logical operations return 1 if they meet a criterion and 0 if they don’t, you can count the number of elements in a vector that meet a criterion by finding the sum of the logical vector result. • The function sum returns the sum of a vector’s elements 23 Logical indexing Example >> age=[45 47 15 13 11]; >> weight=[202 151 113 125 94]; How many teenagers are there? >> age >= 13 & age <= 19 ans = 0 0 1 1 0 >> sum( age >= 13 & age <= 19 ) ans = 2 24 Logical indexing Example >> age=[45 47 15 13 11]; >> weight=[202 151 113 125 94]; How many people weigh more than 200 lbs? >> weight > 200 ans = 1 0 0 0 0 >> sum( weight > 200 ) ans = 1 25 Logical indexing Try It >> age=[45 47 15 13 11]; >> weight=[202 151 113 125 94]; How many adults are there? >> sum( age >= 20 ) ans = 2 How many children are there? >> sum( age < 13 ) ans = 1 26 Logical indexing Try It >> age=[45 47 15 13 11]; >> weight=[202 151 113 125 94]; How many adults weigh more than 200 lbs? >> sum( age >= 20 & weight > 200 ) ans = 1 How many children weigh less than 100 lbs? >> sum( age < 13 & weight < 100 ) ans = 1 27 Logical indexing Tip One good use of logical indexing is the detection and removal of outliers – Outliers are whacky data values, i.e., numbers way off the mean – Conventional definition is any number more than 3 standard deviations from mean, i.e., x is an outlier if x 3 28 Logical indexing Tip >> data = randn( 1, 100 ); >> [ theMax maxIx ] = max( data ) theMax = 3.5784 maxIx = 9 >> [ theMin minIx ] = min( data ) theMin = -2.9443 minIx = 35 % put in new min/max but keep old ones >> data(maxIx+1) = 988.64; >> data(minIx+1) = -2000; 29 Logical indexing Tip - show outliers >> data( abs(data-mean(data)) > 3*std(data) ) ans = 1.0e+003 * 0.9886 -2.0000 30 Logical indexing Remember, can delete elements by specifying indexes to delete and setting to [], e.g., >> v=2:2:10 v = 2 4 6 >> v([2 5]) = [] v = 2 6 8 8 10 31 Logical indexing Can delete elements that meet certain criteria in an analogous way: v(logical_vector) = [] Example Delete all elements that are a multiple of 4 >> v=2:2:10 v = 2 4 6 8 10 >> v(rem(v,4)==0) = [] v = 2 6 10 32 Logical indexing Tip - can remove outliers %% show removeoutliers outliers >> data( data( abs(data-mean(data))>3*std(data) abs(data-mean(data))>3*std(data) ))=[]; >> >> length( data* ) ans = 1.0e+003 ans 0.9886 = 98 -2.0000 >> max( data ) ans = 3.5784 >> min( data ) ans = -2.9443 33 Logical indexing The find function is related to logical indexing. It returns the indexes of the elements of a vector that are nonzero. You can use those indexes to select the elements of a vector that meet a criterion find is most helpful when used on logical vectors 34 Logical indexing Example >> age=[45 47 15 13 11]; >> find( age >= 13 & age <= 19 ) ans = 3 4 How old are the teenagers? >> age( find( age>=13 & age <=19 )) ans = 15 13 35 Logical indexing Example – use find >> age=[45 47 15 13 11]; >> weight=[202 151 113 125 94]; How old is the second teenager? >> indexes = find(age >= 13 & age <= 19) indexes = 3 4 >> age( indexes(2) ) ans = 13 36 Logical indexing Try It – use find >> age=[45 47 15 13 11]; >> weight=[202 151 113 125 94]; How much does the second teenager weigh? >> indexes = find( age >= 13 & age <= 19 ) indexes = 3 4 >> weight( indexes(2) ) ans = 125 37 Logical Indexing NaN (Not a Number) • Built-in constant (can also write nan) • Represents result of mathematically undefined operations, such as 0 / 0 or ∞ - ∞ (infinity minus infinity) • Any logical or relational comparison of two NaN’s returns false, except ~= • isnan(x) returns true if x is NaN and false otherwise 38 Logical Indexing NaN used to mark missing data points Example Two students didn’t show up for a quiz: >> grades=[3 10 8 NaN 0 8 7 5 NaN 6]; >> isnan( grades ) ans = 0 0 0 1 0 0 0 0 1 0 >> find( isnan( grades ) ) ans = 4 9 39 Logical Indexing NaN messes up numerical computations. Remove NaN’s from data first Example >> grades=[3 10 8 NaN 0 8 7 5 NaN 6]; >> mean(grades) ans = NaN >> validGrades = grades( ~isnan(grades) ) validGrades = 3 10 8 0 8 7 5 6 >> mean( validGrades ) ans = 5.8750 40 Logical indexing Tip If you're going to work a lot with data that has missing values, the statistics toolbox can help you. It has functions that compute common statistics and automatically ignore NaN's. They are: nancov, nanmax, nanmean, nanmedian, nanmin, nanstd, nansum, nanvar Example >> v = [ 10 NaN 6 2 NaN ]; >> mean( v ) ans = NaN >> nanmean( v ) ans = 6 41 Logical Indexing In the fall of 2004 non-freshmen students at Miami University were surveyed. One of the questions was to write the number of hours of anti-alcohol education the students had received at Miami. The responses are numbers from 0 to 4 with 0 to 3 being the actual number of hours and 4 representing more than 3 hours. Some students did not respond at all. Load the answers to the question with the command >> allAnswers = load( 'survey.txt' ) 42 Logical Indexing Try It In the survey, students who didn’t answer the question are represented by NaN. Answer the following questions (without nanxxx functions): • How many students were in the survey? • How many students did not answer the survey question? 43 Logical indexing >> allAnswers=load('survey.txt'); % Number of students in survey? >> length(allAnswers) ans = 531 % Number of students not responding? >> sum(isnan(allAnswers)) ans = 59 44 Logical Indexing Try It Make a vector for only the students who answered. Use it to answer the following questions about the amount of college alcohol-prevention education the students had. Are all the values in your new vector legal, i.e., between 0 and 4 inclusive? 45 Logical indexing >> good=allAnswers( ~isnan(allAnswers) ); % Are all responses legal (>=0 and <=4)? >> all(good>=0 & good<=4 ) ans = 1 46 Logical Indexing Try It • What percentage didn’t have any prevention education? • For every student who had the maximum amount of prevention education, how many had none? • What was the average number of hours of prevention education for students who had 1, 2, or 3 such hours? 47 Logical indexing % Percentage uneducated? >> 100*sum(good==0)/length(good) ans = 39.6186 % uneducated / maximally educated? >> sum(good==0)/sum(good==4) ans = 1.8515 % average for those with some but not all >> mean( good( good>=1 & good<=3 ) ) ans = 2.0435 48 Logical indexing FINAL POINT Note that we have answered all the questions 1. Without using if-statements 2. Without using loops Logical indexing makes cleaner, faster code! 49 Logical indexing Questions? 50 The End 51