14  12c. (a) EXCLAMATION POINT (i.e the “not” operator) (b) is.na( LOGICAL_VECTOR )

#########################################################################.
#
# USING THE EXCLAMATION POINT (i.e "not") OPERATOR
#
#   ! SOME_LOGICAL_VECTOR    # (i.e. exclamation point before a logical vector)
#
# It flips TRUEs and FALSEs.  (i.e. changes TRUE to FALSE and changes FALSE to TRUE)
#########################################################################.
#########################################################################.

logicalValues <- c(TRUE, FALSE, TRUE, TRUE)
logicalValues
[1]  TRUE FALSE  TRUE  TRUE
!logicalValues    # change TRUE to FALSE and change FALSE to TRUE
[1] FALSE  TRUE FALSE FALSE
logicalValues    # the original vector didn't change
[1]  TRUE FALSE  TRUE  TRUE

14.1 is.na( someVector )

#########################################################################.
#
# is.na
#
# is.na ( someVector ) tests to see if the values are NA.
# is.na returns a logical vector. Example:
# 
#   > is.na(c(10,NA,20,30,NA))
#   [1] FALSE TRUE FALSE FALSE TRUE
#
#########################################################################.

# EXAMPLES

#---------------------------------------------------------------------------.
# QUESTION: A teacher recorded grades of her students on a test in the vector grades.
# Some students didn't take the test yet. For those students she recorded a grade of 
# NA. (see the questions below)
#---------------------------------------------------------------------------.

grades = c(NA,85,NA,90,88)   # NA is used for students who didn't take the test yet.
grades
[1] NA 85 NA 90 88
mean(grades)    # NA
[1] NA
mean(grades, na.rm=TRUE)  # 87.6667
[1] 87.66667
grades == NA   # NA NA NA NA NA
[1] NA NA NA NA NA
# original:    grades == NA
#              c(NA,85,NA,90,88) == NA
#              c(NA==NA,85==NA,NA==NA,90==NA,88==NA) 
#              NA NA NA NA NA 


grades != NA   # NA NA NA NA NA
[1] NA NA NA NA NA
# Show a logical vector that indicates which grades are NAs

is.na(grades)     # TRUE FALSE TRUE FALSE FALSE
[1]  TRUE FALSE  TRUE FALSE FALSE
# Show the actual NAs

grades[ is.na(grades) ]   # NA NA 
[1] NA NA
# original:    grades[ is.na(grades) ]
#              grades[ is.na(c(NA,85,NA,90,88)) ]
#              grades[ c(TRUE,FALSE,TRUE,FALSE,FALSE) ]
#              NA NA


# Show the just the grades that are NOT NA grades
# REMEMBER (see above) that the ! will flip TRUE to FALSE and FALSE to TRUE


grades [ !is.na(grades) ]   # 85 90 88
[1] 85 90 88
# original:    grades[ !is.na(grades) ]
#              grades[ !is.na(c(NA,85,NA,90,88)) ]
#              grades[ c(FALSE,TRUE,FALSE,TRUE,TRUE) ]
#              85 90 88


# How many students did not take the test yet (i.e. grade is NA)
sum( is.na(grades) )
[1] 2
# what percent of the class DID take the test already?
mean( !is.na(grades) )               # one answer (this is the best answer)
[1] 0.6
1 - mean (is.na(grades))             # another answer
[1] 0.6
sum(!is.na(grades)) / length(grades) # a third answer
[1] 0.6

14.2 — Practice —

#########################################################.
# QUESTION
#
# Write a function with the following signature
#
#    positionsOfMin = function( vec ){
#        # YOUR CODE GOES HERE
#    }
#
# The function should return a vector with the positions
# of the minimum value in the vector.
#
# EXAMPLE 1:
#    > positionsOfMin(c(10, 5, 2, 100, 2, 35))
#    [1] 3 5
#
# EXAMPLE 2:
#    > positionsOfMin(c(40, 30, 20, 10))
#    [1] 4
#########################################################.
# ANSWER 1 - this version is somewhat longer than it needs to be.
#            The code is spread out on multiple lines so that you can follow
#            along with the debugger to understand how everything works.

positionsOfMin = function( vec ){
  
  allPositions = 1:length(vec)
  smallest = min(vec)
  tf = vec == smallest
  allPositions[tf]
}

# check the examples
positionsOfMin(c(10, 5, 2, 100, 2, 35))   # 3 5
[1] 3 5
positionsOfMin(c(40, 30, 20, 10)) # 4
[1] 4
# ANSWER 2 - this version is more concise but results in the same values.
positionsOfMin = function( vec ){
  (1:length(vec)) [vec == min(vec)]
}

# check the examples
positionsOfMin(c(10, 5, 2, 100, 2, 35))   # 3 5
[1] 3 5
positionsOfMin(c(40, 30, 20, 10)) # 4
[1] 4
#########################################################.
# QUESTION
#
# Write a function with the following signature
#
#    addToMinValues = function( nums , value ){
#        # YOUR CODE GOES HERE
#    }
#
# nums is expected to be a numeric vector
#
# value is expected to be a single number
#
# The return value should be the same as nums with the value
# added to the minimum values in nums.
#
# HINT - feel free to use the positionsOfMin function that 
# you defined in the previous question as part of the answer.
#
# EXAMPLE 1:
#    > addToMinValues(c(10, 5, 2, 100, 2, 35) , 100)
#    [1] 10 5 102 100 102 35
#
# EXAMPLE 2:
#    > positionsOfMin(c(40, 30, 20, 10), 200)
#    [1] 40 30 20 210
#########################################################.
addToMinValues = function( nums, value ) {
  positions = positionsOfMin(nums)
  nums[positions] = nums[positions] + value
  return(nums)
}

# check the examples
addToMinValues(c(10, 5, 2, 100, 2, 35), 100)   
[1]  10   5 102 100 102  35
addToMinValues(c(40, 30, 20, 10), 200) 
[1]  40  30  20 210