13  13. Indexing with NEGATIVE numbers

##################################################.
# Indexing with NEGATIVE numbers
# e.g. 
#      stuff[-3]
#      stuff[c(-3,-5)]
#      stuff[-c(3,5)]
#      stuff[-seq(1,length(stuff),by=3)]
##################################################.

#-------------------------------------------------------------------------.
# If the index is a negative number or a vector of negative numbers, 
# all except those positions will be accessed.                       
#-------------------------------------------------------------------------.

stuff <- c(10,20,30,40,50,60)

stuff
[1] 10 20 30 40 50 60
stuff[-2]   # 10 30 40 50 60 (all except for 2nd value)
[1] 10 30 40 50 60
stuff       # 10 20 30 40 50 60 (stuff didn't change)
[1] 10 20 30 40 50 60
stuff[c(-2,-4)] # 10 30 50 60  (all except 2nd and 4th values)   ####
[1] 10 30 50 60
stuff 
[1] 10 20 30 40 50 60
stuff[-c(2,4)]  # 10 30 50 60  (same result)    ####
[1] 10 30 50 60
stuff[ - seq(3, length(stuff), by=3) ] # 10 20 40 50  (all except every 3rd value)
[1] 10 20 40 50
stuff[ seq(-3, -length(stuff), by=-3) ] # same result
[1] 10 20 40 50
##################################################################.
# QUESTION - part a
#
# Write a command that displays the entire vector, x, except
# for the first and last values of x.
#
# EXAMPLE 1
#   > x = c(10,20,30,40,50)
#   > YOUR CODE GOES HERE
#   [1] 20 30 40
#
# EXAMPLE 2
#   > x = c(100,30,999)
#   > YOUR CODE GOES HERE
#   [1] 30
#
# DO THE ANSWER TWO DIFFERENT WAYS
# - ONCE WITH POSITIVE INDEX NUMBERS
# - ONCE WITH NEGATIVE INDEX NUMBERS
##################################################################.
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# ANSWER : Positive index value
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

# Example 1
x = c(10,20,30,40,50)
x = x[2:(length(x)-1)]      # ANSWER
x
[1] 20 30 40
# Example 2
x = c(100,30,999)
x = x[2:(length(x)-1)]
x
[1] 30
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# ANSWER: Negative index value
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

# Example 1
x = c(10,20,30,40,50)
x = x[c(-1,-length(x))]
x
[1] 20 30 40
# Example 2
x = c(100,30,999)
x = x[c(-1,-length(x))]
x
[1] 30
##################################################################.
# QUESTION - part b
#
# Similar to previous question. However, this time, 
# define a FUNCTION named removeFirstAndLast that takes a single
# argument named vec. The function should return the values in 
# vec but without the first and last values.
#
# EXAMPLES
#   > removeFirstAndLast ( c(10,20,30,40,50) )
#   [1] 20 30 40
#
#   > removeFirstAndLast( c(100,30,999) )
#   [1] 30
##################################################################.
#>>>>>>>>>>>>>>>>>>>
# ANSWER
#>>>>>>>>>>>>>>>>>>>

# Using positive index numbers

removeFirstAndLast = function ( vec ){
  
  vec [ 2 : (length(vec) - 1)   ] 
}


removeFirstAndLast ( c(10,20,30,40,50) )   # 20 30 40
[1] 20 30 40
removeFirstAndLast( c(100,30,999) )        # 30 
[1] 30
removeFirstAndLast = function ( vec ){
  
  vec [ c( -1 , - length(vec) ) ]  
}

removeFirstAndLast ( c(10,20,30,40,50) )   # 20 30 40
[1] 20 30 40
removeFirstAndLast( c(100,30,999) )        # 30 
[1] 30
##################################################################.
# QUESTION - part c
#
# Define a function named removeFirstLastFew that takes the following arguments
#
# ARGUMENTS 
#    vec - a vector that is expected to contain a few values
#    amount - the number of values to trim from the beginning and end of vec
#
#    You may assume that length(vec) is greater than or equal to amount * 2.
#
#
# EXAMPLE A
#   > removeFirstLastFew ( vec = c(10,20,30,40,50,60,70), amount = 2)
#   [1] 30 40 50  
#
# EXAMPLE B
#   > removeFirstLastFew ( vec = c(90,100,80,65,92), amount = 1)
#   [1] 100 80 65  
#
# EXAMPLE C
#   > removeFirstLastFew ( vec = c(10,20,30,40,50,60,70), amount = 3)
#   [1] 40  
#
# DO THE ANSWER TWO DIFFERENT WAYS
# - ONCE WITH POSITIVE INDEX NUMBERS
# - ONCE WITH NEGATIVE INDEX NUMBERS
##################################################################.
#>>>>>>>>>>>>>>>>>>>>>>>>>
#> ANSWER
#>>>>>>>>>>>>>>>>>>>>>>>>>

# Using positive index numbers
removeFirstLastFew = function( vec, amount) {
  startingPosition = amount + 1
  endingPosition = length(vec) - amount
  vec[ startingPosition:endingPosition]
}


removeFirstLastFew(c(10,20,30,40,50,60,70), 3)
[1] 40
removeFirstLastFew(c(10,20,30,40,50,60,70), 2)
[1] 30 40 50
removeFirstLastFew(c(10,20,30,40,50,60,70), 1)
[1] 20 30 40 50 60
removeFirstLastFew(c(10,20,30,40,50,60,70), 4)
[1] 50 40 30
#>>>>>>>>>>>>>>>>>>>>>>>>>
#> ANSWER
#>>>>>>>>>>>>>>>>>>>>>>>>>

# Using positive index numbers
removeFirstLastFew = function( vec, amount) {
  
  firstFew = 1:amount
  
  # Pay special attention to the "+1" in the next line of code.
  # To see why the +1 is needed try a few examples "by hand". 
  lastFew =  (length(vec)-amount+1):length(vec)     
  
  vec[ c(-firstFew, -lastFew) ]
}


removeFirstLastFew(c(10,20,30,40,50,60,70), 3)
[1] 40
removeFirstLastFew(c(10,20,30,40,50,60,70), 2)
[1] 30 40 50
removeFirstLastFew(c(10,20,30,40,50,60,70), 1)
[1] 20 30 40 50 60
removeFirstLastFew(c(10,20,30,40,50,60,70), 4)
numeric(0)
##################################################################.
# QUESTION - part a
#
# Write a command that returns the contents of the vector, x,
# in reverse order. Write the command so that it works
# no matter how many elements the vector contains.
#
# Your command must work UNCHANGED for both examples
# (and all other examples that are not shown below).
#
# EXAMPLE 1
#   > x = c(10,20,30,40,50)
#   > YOUR CODE GOES HERE
#   [1] 50 40 30 20 10
#
# EXAMPLE 2
#   > x = c(100,30,999)
#   > YOUR CODE GOES HERE
#   [1] 999 30 100
##################################################################.
# EXAMPLE 1 - Set up some values
x = c(10,20,30,40,50)
x[length(x):1]            # **ANSWER**
[1] 50 40 30 20 10
# EXAMPLE 2 - Set up some values
x = c(100,30,999)
x[length(x):1]          # **ANSWER**
[1] 999  30 100
##################################################################.
# QUESTION - part b
# 
# Same as above but this time make a function named myrev.
# The myrev function should take a single argument named x.
# The function return the reverse of x.
#
# Note - there is a function in R named rev that does this. 
# your code should create a function named myrev that does the 
# same thing as the built in rev function.
#
# HINTS 
#   - your answer should use the length function
#   - your answer should use the : operator or the seq function
#
# EXAMPLE 1
#   > myrev ( c(10,20,30,40,50) )
#   [1] 50 40 30 20 10
#
# EXAMPLE 2
#   > myrev ( x=c(100,30,999) )
#   [1] 999 30 100
##################################################################.
# ANY OF THE FOLLOWING FUNCITON DEFINTIONS WILL WORK JUST FINE.  # **ANSWER**
myrev = function( x ){  # **ANSWER**
  x[length(x):1]        # **ANSWER**
}                       # **ANSWER**

myrev = function( x ){   # **ANSWER**
  return(x[length(x):1]) # **ANSWER**
}                        # **ANSWER**


myrev = function( x ){      # **ANSWER**
  answer = x[length(x):1]   # **ANSWER**
  return(answer)            # **ANSWER**
}                           # **ANSWER**

myrev = function( x ){    # **ANSWER**
  answer = x[length(x):1] # **ANSWER**
  answer                  # **ANSWER**
}                         # **ANSWER**

# EXAMPLE 1
myrev ( c(10,20,30,40,50) ) # 50 40 30 20 10
[1] 50 40 30 20 10
# EXAMPLE 2
myrev ( x=c(100,30,999) ) # 999 30 100
[1] 999  30 100
# DONT DO THIS!!!!
# DO NOT RETURN THE VALUE OF AN ASSIGNMENT STATEMENT.
# THE VALUE OF AN ASSIGNMENT STATEMENT IS "INVISIBLE"

myrev = function( x ){         # **ANSWER** - DON'T DO THIS
  answer = x[length(x):1]      # **ANSWER** - DON'T DO THIS
}                              # **ANSWER** - DON'T DO THIS

myrev ( c(10,20,30,40,50) ) # no results are displayed  # **ANSWER** - DON'T DO THIS  

myrev ( x=c(100,30,999) ) #  no results are displayed   # **ANSWER** - DON'T DO THIS
##########################################################################.
# QUESTION - part a
# 
# Write code that displays every other value of x.
# The same code should work for all values of x.
#
# HINTS: 
#   - Use the length function to make it work no matter how many values
#     are in x.
#
#   - use the seq function
#
# EXMPLE 1
#
#    > x = c(100,200,300,400)
#    > YOUR CODE GOES HERE (must be same code as for EXAMPLE 2)
#    [1] 100 300
#
# EXMPLE 2
#
#    > x = c(83,99,82,67,85,100,89)
#    > YOUR CODE GOES HERE (must be same code as for EXAMPLE 1)
#    [1] 83 82 85 89
#
##########################################################################.
###########.
# ANSWER 
###########.

# EXAMPLE 1

x = c(100,200,300,400)
x [ seq(1, length(x), by=2) ]     # **ANSWER**
[1] 100 300
# EXAMPLE 2

x = c(83,99,82,67,85,100,89)
x [ seq(1, length(x), by=2) ]     # **ANSWER**
[1] 83 82 85 89
##################################################################.
# QUESTION - part b
#
# Write a command that returns two copies of every other element 
# that is in x, starting with the 1st. Write the command so that it will work
# correctly no matter how many elements the vector contains.
#
# HINTS 
#   - Build on your from the previous part of this question
#
#   - You answer should use the rep function
#
#
# EXAMPLE 1
#   > x = c(10, 20, 30, 40, 50)
#   > # YOUR CODE GOES HERE
#   [1] 10 10  30 30 50 50 
#
# EXAMPLE 2
#   > x = c(92, 100, 79)
#   > # YOUR CODE GOES HERE
#   [1] 92 92  79 79
##################################################################.
###########.
# ANSWER 
###########.

# EXAMPLE 1

x = c(10, 20, 30, 40, 50)
rep(x[ seq(1, length(x), by=2) ], each=2)    # 10 10 30 30 50 50   
[1] 10 10 30 30 50 50
# EXAMPLE 2
x = c(92, 100, 79)
rep(x[ seq(1, length(x), by=2) ], each=2)    # 92 92 79 79      
[1] 92 92 79 79
#-----------------------------------------------------------------.
# REMEMBER - 2 ways we learned about (so far) to "index a vector"
#            (i.e. to identify specific values in the vector)
#-----------------------------------------------------------------.

# FIRST WAY - use a vector in [brackets] that specifies the positions you want

bigNumbers = c(1000,2000,3000,4000,5000)

bigNumbers [ c( 1, 3) ]    # 1000 3000
[1] 1000 3000
# SECOND WAY - use negative numbers to indicate the positions you DON'T want

bigNumbers [ c(-1, -4, -5)]   # 2000 3000
[1] 2000 3000
# the same thing ...

bigNumbers [ - c(1, 4, 5)]   # 2000 3000
[1] 2000 3000

13.1 DON’T mix positive and negative index numbers

You may index either - with POSITIVE numbers or - with NEGATIVE numbers

BUT DO NOT mix positive and negative numbers in the index. That will generate an ERROR as the following example shows.

stuff = c(10,20,30,40,50)

stuff[c(2,3)]
[1] 20 30
stuff[c(-2,-3)]
[1] 10 40 50
stuff[c(-2,3)]   # ERROR - you may not mix positive and negative index numbers
Error in stuff[c(-2, 3)]: only 0's may be mixed with negative subscripts
##############################################################.
# QUESTION
#
# Write a function, longestSeq that takes a single argument named nums.
# The function should return the sequence counting
# by ones, starting from the smallest value in nums to the largest value
# in nums.
#
# HINT - you can use the functions min and max in your answer
#
# EXAMPLE 1
#       > longestSeq( c ( 3, 9, 4, 2, 5, 5, 4, 8 ))
#       [1] 2 3 4 5 6 7 8 9
#
# EXAMPLE 2
#       > longestSeq( c(100, 99, 103, 100))
#       [1] 99  100  101  102  103
##############################################################.
# ANSWER 
longestSeq = function(nums) {   # **ANSWER**
  min(nums):max(nums)            # **ANSWER**
}                               # **ANSWER**

# ANOTHER ANSWER                 # **ANSWER**
longestSeq = function(nums) {    # **ANSWER**
  sorted = sort(nums)             # **ANSWER**
  sorted[1]:sorted[length(nums)]  # **ANSWER**
}                                # **ANSWER**

# YET ANOTHER ANSWER           # **ANSWER**
longestSeq = function(nums) {  # **ANSWER**
  lowest = min(nums)            # **ANSWER**
  highest = max(nums)           # **ANSWER**
  lowest:highest                # **ANSWER**
}                              # **ANSWER**

# EVEN YET ONE MORE ANSWER    # **ANSWER**
longestSeq = function(nums) { # **ANSWER**
  lowest = min(nums)           # **ANSWER**
  highest = max(nums)          # **ANSWER**
  answer = lowest:highest      # **ANSWER**
  answer                       # **ANSWER**
}                             # **ANSWER**

# EXAMPLE 1
longestSeq( c ( 3, 9, 4, 2, 5, 5, 4, 8 ))   # 2 3 4 5 6 7 8 9
[1] 2 3 4 5 6 7 8 9
# EXAMPLE 2
longestSeq( c(100, 99, 103, 100))  # 99  100  101  102  103
[1]  99 100 101 102 103
###############################################################################.
# QUESTION    TOPICS:  indexing with numbers ####
# 
# Write a function named squish, that takes a single argument named nums.
# The function should 
#
#   add together the first value with the 2nd value
#   add together the 2nd value with the 3rd value
#   etc.
#
# EXAMPLE 1:
#   > squish( c(10,20,30,40) )
#   [1] 30 50 70
#
# EXAMPLE 2:
#   > squish( c(100,50,30,200,150,10) )
#   [1] 150 80 230 350 160
#
#
# PART A - write the answer by indexing with POSITIVE numbers
# PART B - write the answer by indexing with NEGATIVE numbers
#############################################################################.
#--------------------------------------------------------------.
# PART A - write the answer by indexing with POSITIVE numbers
#--------------------------------------------------------------.

# First think about the problem. It often is useful to start thinking
# about the problem with a simple example.
#
# In the example, we are given the vector c(10,20,30,40)
# For this example, adding together 
#    the 1st number with the 2nd number, 
#    the 2nd number with the 3rd number, 
#    etc
# 
# Is the same as adding together the following two vectors:
#    c(10,20,30) + c(20,30,40)
#
# The 1st vector, c(10,20,30) is the original vector without the last number.
# The 2nd vector, c(20,30,40) is the original vector without the first number.
# 
# Therefore our function needs to calculate these two vectors and then add them.
# We can do this with either POSITIVE index numbers or NEGATIVE index numbers
# as shown below.

squish = function (vec) {
  allButLast = vec[1:(length(vec)-1)]
  allButFirst = vec[2:length(vec)]
  
  answer = allButLast + allButFirst
  
  return(answer)
}

# Make sure both examples work
squish(c(10,20,30,40))
[1] 30 50 70
squish( c(100,50,30,200,150,10) )
[1] 150  80 230 350 160
#--------------------------------------------------------------.
# ANSWER - PART B - write the answer by indexing with NEGATIVE numbers
#--------------------------------------------------------------.

# I recommend you first see the analysis
# in the answer to PART A above.

squish = function (vec) {
  allButLast = vec[-length(vec)]
  allButFirst = vec[-1]
  
  answer = allButLast + allButFirst
  
  return(answer)
}

# Make sure both examples work
squish(c(10,20,30,40))
[1] 30 50 70
squish( c(100,50,30,200,150,10) )
[1] 150  80 230 350 160

© 2025 Y. Rosenthal. All rights reserved.