``````###############################################################################.
###############################################################################.
##
## INTRODUCING [[double-bracket]] NOTATION FOR INDEXING LISTS (and also vectors)
##
## A new notation that we have not seen yet for indexing both vectors and lists
## is to use [[double-brackets]] to contain the index information instead
## of [single-brackets]. For example
##
##    someObject[3]     # [single-bracket] notation
##    someObject[[3]]   # [[double-bracket]] notation
##
## [[double-brackets]] have a slightly different meaning from [single-brackets].
##
## [[double-brackets]] work a little differently with vectors and with lists.
##
###############################################################################.
###############################################################################.``````
``````#----------------------------------------------------------------------.
# USING [[double-brackets]] WITH LISTS
#
# Using [[double-brackets]] to index into a LIST is similar to using
# double-brackets to index into a vector in the following way:
#
#     - You CAN use POSITIVE NUMBERS numbers in the [[double-brackets]]
#       With a LIST you MAY specify more than one POSITIVE number in the
#       [[double-brackets]]. (With vectors you are only able to specify
#       one positive number). We'll discuss below exactly how this works.
#
#  HOWEVER
#
#     - You CANNOT use negative numbers in the [[double-brackets]]
#
#     - You CANNOT use logical values in the [[double-brackets]]
#
#----------------------------------------------------------------------.

# setup a list to work with

gradebook = list( c("bob", "charlie", "frank"), # student names
c(70,80,90),                  # grades from first test
c(75,85,88),                  # grades from second test
c(TRUE, FALSE,FALSE))         # TRUE for honors students

``````[[1]]
[1] "bob"     "charlie" "frank"

[[2]]
[1] 70 80 90

[[3]]
[1] 75 85 88

[[4]]
[1]  TRUE FALSE FALSE``````
``````# The following are ERRORS!

gradebook[[-1]]    # ERROR - don't use negative values in the [[double-brackets]]``````
``Error in gradebook[[-1]]: invalid negative subscript in get1index <real>``
``gradebook[[c(TRUE,FALSE)]] # ERROR - don't use logicals in [[double-brackets]]``
``Error in gradebook[[c(TRUE, FALSE)]]: attempt to select less than one element in integerOneIndex``

## 23.1 someList[1] vs someList[[1]]

``````#............................................................................
# QUESTION
#
# Take a minute to CAREFULLY NOTICE the difference between the following
# two commands.
#
# What is the difference???
#
#      [[1]]
#      [1] "bob"     "charlie" "frank"
#
#
#      [1] "bob" "charlie" "frank"
#
#............................................................................

gradebook[1]  # return value is shown below``````
``````[[1]]
[1] "bob"     "charlie" "frank"  ``````
``````# > gradebook[1]
# [[1]]
# [1] "bob"     "charlie" "frank"

gradebook[[1]]  # return value is shown below``````
``[1] "bob"     "charlie" "frank"  ``
``````# > gradebook[[1]]
# [1] "bob" "charlie" "frank"

#............................................................................
#
#    gradebook[1]    # returns a LIST of that contains ONE VECTOR
#
#    gradebook[[1]]  # returns ONE VECTOR
#............................................................................

mode( gradebook [1])   # returns a list``````
``[1] "list"``
``mode( gradebook [[1]]) # returns a character vector``
``[1] "character"``
``````# Similarly for other positions ....

``[1] 70 80 90``
``mode( gradebook [2])   # list``
``[1] "list"``
``mode( gradebook [[2]]) # numeric``
``[1] "numeric"``

## 23.2 USING [single-brackets] TO INDEX INTO A LIST USING MORE THAN ONE POSITIVE NUMBER

``````#---------------------------------------------------------------------.
# USING [single-brackets] TO INDEX INTO A LIST
# USING MORE THAN ONE POSITIVE NUMBER
# is conceptually similar to using more than one positive number in single brackets
# with VECTORS.
#
# When indexing into a VECTOR you get back just the specified values in a new VECTOR.
#
# When indexing into a LIST  you get back just the specified values in a new LIST.
#---------------------------------------------------------------------.

gradebook[ c(1,2) ]   # a list of 2 items, i.e. the names and the test1 grades``````
``````[[1]]
[1] "bob"     "charlie" "frank"

[[2]]
[1] 70 80 90``````
``mode(gradebook[c(1,2)])  # list``
``[1] "list"``

## 23.3 USING [[double-brackets]] TO INDEX INTO A LIST USING MORE THAN ONE POSITIVE NUMBER

``````#---------------------------------------------------------------------.
# RECURSIVE INDEXING
#
# WITH LISTS YOU CAN USE THE [[double-brackets]] with more than
# one position number - it applies the position numbers to the items
# you get back one at a time. This is known as "recursive indexing".
#---------------------------------------------------------------------.

gradebook[[c(1,2)]] # "charlie" - ie. from the 1st item in the list get the 2nd item``````
``[1] "charlie"``
``gradebook[[c(3,3)]] # 88 - i.e. from the 3rd item in the list get the 3rd item``
``[1] 88``
``gradebook[[c(3,2)]] # 85 - i.e. from the 3rd item in the list get the 2nd item``
``[1] 85``
``gradebook[[3]]      # 75 85 95``
``[1] 75 85 88``
``gradebook[[4]]      # TRUE FALSE FALSE``
``[1]  TRUE FALSE FALSE``

## 23.4 Using the length function with lists (it can be tricky)

``````#--------------------------------------------.
# length( SOME_LIST )
#    returns the number of objects in the list
#
#     vs
#
# length( SOME_LIST[[1]] )
#    returns the number of items in the first object in the list
#
#    vs
#
# length( SOME_LIST[1] )
#    DONT DO THIS - IT ALWAYS RETURNS 1  - WHY?
#------------------------------------------------

rm(list=ls()) # Start from scratch
gradebook = list( c("bob", "charlie", "frank"), # student names
c(70,80,90),                  # grades from first test
c(75,85,88),                  # grades from second test
c(TRUE, FALSE,FALSE))         # TRUE for honors students

##############################################.
# Let's see the lengths of the following ...
##############################################.
length(gradebook)       # 4 - i.e. four objects in the list ``````
``[1] 4``
``length(gradebook[[1]])  # 3 - i.e. three student names in the first object of the list``
``[1] 3``
``````# Be careful - if you use single brackets you will get back a "list".
# Therefore the following all return a list of length 1.
length(gradebook[1])    # 1 - i.e. this is a LIST that contains one vector``````
``[1] 1``
``````#############################.
# Let's see the actual values
#############################.

``````[[1]]
[1] "bob"     "charlie" "frank"

[[2]]
[1] 70 80 90

[[3]]
[1] 75 85 88

[[4]]
[1]  TRUE FALSE FALSE``````
``````# The first item in the list (i.e. a full vector)
``[1] "bob"     "charlie" "frank"  ``
``````# A new list that contains just the 1st item of the original list vector)
``````[[1]]
[1] "bob"     "charlie" "frank"  ``````
``#etc``

## 23.5 Summary - [single-brackets] vs [[double-brackets]]

``````###############################################################################.
#
# If you keep the following idea in mind, a lot of the rules become
# easier to remember:
#
#   - [single-brackets] are intended to allow you to identify MULTIPLE objects
#     in a list (and in a vector).
#
#   - [[double-brackets]] are intended to allow you to identify A SINGLE object
#     in a list (and in a vector too - we'll see this later). However, when
#     using a list, a SINGLE object might be a complete vector (or even
#     a complete list)
###############################################################################.``````

## 23.6 — Practice —

``````#########################################################.
# Use the following to answer the questions below
#########################################################.
rm(list=ls()) # Start from scratch
gradebook = list( c("bob", "charlie", "frank", "sam"),# student names
c(70,     80,        90,      100), # grades from 1st test
c(75,     85,        88,      92),  # grades from 2nd test
c(TRUE,   FALSE,     FALSE,   TRUE))# TRUE for honors students``````
``str(gradebook)  # see the structure``
``````List of 4
\$ : chr [1:4] "bob" "charlie" "frank" "sam"
\$ : num [1:4] 70 80 90 100
\$ : num [1:4] 75 85 88 92
\$ : logi [1:4] TRUE FALSE FALSE TRUE``````
``gradebook # (see the actual values)``
``````[[1]]
[1] "bob"     "charlie" "frank"   "sam"

[[2]]
[1]  70  80  90 100

[[3]]
[1] 75 85 88 92

[[4]]
[1]  TRUE FALSE FALSE  TRUE``````
``# View(gradebooks)  # see the structure - try this command yourself``
``````##########################################################################.
# QUESTION
#
# NOTE that many R commands and functions require a vector, not a list.
# Therefore in these situations you will need to retrieve a vector
# from the list using [[double-brackets]]
#
# Given the gradebook data shown above, write a command to calculate
# the average on the 1st exam.
##########################################################################.``````
``````###########.
###########.

# Use [[double-brackets]] to get the data for the first exam
# and take the mean.

``[1] 85``
``````##############################.
# THE FOLLOWING IS WRONG!!!!
##############################.

# Note that the following does NOT produce the correct results
# since gradebook[2] is a LIST and you cannot take the mean of a list.

mean(gradebook[2])  # WRONG - gradebook[2] is a LIST - you need a VECTOR``````
``````Warning in mean.default(gradebook[2]): argument is not numeric or logical:
returning NA``````
``[1] NA``
``````##########################################################################.
# QUESTION
#
# Notice that the data in the list above is a set of parallel vectors.
# Write a command to show the name of the students who got above average
# on the 1st test.
##########################################################################.``````
``````#####################################.
# ANSWER (using a few lines of code)
#####################################.

students [ test1 > mean(test1) ]  # show the students names``````
``[1] "frank" "sam"  ``
``````#####################################.
# ANSWER (in one line of code)
#####################################.

``[1] "frank" "sam"  ``
``````#############################################################################.
# QUESTION
# Write a command to return a vector that contains both the test1 and test2
# grades for the 3rd student
#############################################################################.``````
``````###########.
###########.
``[1] 90 88``

## 23.7 — Practice —

``````#########################################################.
# Use the following to answer the questions below
#########################################################.
rm(list=ls())  # start from scratch

c("Intro to IDS", "Prof. Jones"),
list( "Fall 2023",
c("bob", "charlie", "frank"), # student names
c(70,80,90),                  # grades from first test
c(75,85,88),                  # grades from second test
c(TRUE, FALSE,FALSE)),         # TRUE for honors students
list("Spring 2024",
c("bob", "charlie", "frank"), # student names
c(70,80,90),                  # grades from first test
c(75,85,88),                  # grades from second test
c(TRUE, FALSE,FALSE))         # TRUE for honors students
)``````
``str(gradebooks)  # see the structure``
``````List of 3
\$ : chr [1:2] "Intro to IDS" "Prof. Jones"
\$ :List of 5
..\$ : chr "Fall 2023"
..\$ : chr [1:3] "bob" "charlie" "frank"
..\$ : num [1:3] 70 80 90
..\$ : num [1:3] 75 85 88
..\$ : logi [1:3] TRUE FALSE FALSE
\$ :List of 5
..\$ : chr "Spring 2024"
..\$ : chr [1:3] "bob" "charlie" "frank"
..\$ : num [1:3] 70 80 90
..\$ : num [1:3] 75 85 88
..\$ : logi [1:3] TRUE FALSE FALSE``````
``gradebooks # (see the actual values)``
``````[[1]]
[1] "Intro to IDS" "Prof. Jones"

[[2]]
[[2]][[1]]
[1] "Fall 2023"

[[2]][[2]]
[1] "bob"     "charlie" "frank"

[[2]][[3]]
[1] 70 80 90

[[2]][[4]]
[1] 75 85 88

[[2]][[5]]
[1]  TRUE FALSE FALSE

[[3]]
[[3]][[1]]
[1] "Spring 2024"

[[3]][[2]]
[1] "bob"     "charlie" "frank"

[[3]][[3]]
[1] 70 80 90

[[3]][[4]]
[1] 75 85 88

[[3]][[5]]
[1]  TRUE FALSE FALSE``````
``# View(gradebooks)  # see the structure - try this command yourself``
``mean( gradebooks[[2]][[3]] )``
``[1] 80``
``max( gradebooks[[2]][[3]], gradebooks[[2]][[4]] )``
``[1] 90``
``length(gradebooks)``
``[1] 3``
``length(gradebooks[c(1,2)])  ``
``[1] 2``
``gradebooks[c(1,2)]``
``````[[1]]
[1] "Intro to IDS" "Prof. Jones"

[[2]]
[[2]][[1]]
[1] "Fall 2023"

[[2]][[2]]
[1] "bob"     "charlie" "frank"

[[2]][[3]]
[1] 70 80 90

[[2]][[4]]
[1] 75 85 88

[[2]][[5]]
[1]  TRUE FALSE FALSE``````
``str(gradebooks[c(1,2)])``
``````List of 2
\$ : chr [1:2] "Intro to IDS" "Prof. Jones"
\$ :List of 5
..\$ : chr "Fall 2023"
..\$ : chr [1:3] "bob" "charlie" "frank"
..\$ : num [1:3] 70 80 90
..\$ : num [1:3] 75 85 88
..\$ : logi [1:3] TRUE FALSE FALSE``````
``gradebooks[c(1,3)]``
``````[[1]]
[1] "Intro to IDS" "Prof. Jones"

[[2]]
[[2]][[1]]
[1] "Spring 2024"

[[2]][[2]]
[1] "bob"     "charlie" "frank"

[[2]][[3]]
[1] 70 80 90

[[2]][[4]]
[1] 75 85 88

[[2]][[5]]
[1]  TRUE FALSE FALSE``````
``str(gradebooks[c(1,3)])``
``````List of 2
\$ : chr [1:2] "Intro to IDS" "Prof. Jones"
\$ :List of 5
..\$ : chr "Spring 2024"
..\$ : chr [1:3] "bob" "charlie" "frank"
..\$ : num [1:3] 70 80 90
..\$ : num [1:3] 75 85 88
..\$ : logi [1:3] TRUE FALSE FALSE``````
``length(gradebooks[[c(1,2)]])``
``[1] 1``
``gradebooks[[c(1,2)]]``
``[1] "Prof. Jones"``
``str(gradebooks[[c(1,2)]])``
`` chr "Prof. Jones"``
``length(gradebooks[[2]])``
``[1] 5``
``gradebooks[[2]][3]``
``````[[1]]
[1] 70 80 90``````
``mode( gradebooks[[2]][3] )``
``[1] "list"``
``length( gradebooks[[2]][3] )``
``[1] 1``
``gradebooks[[2]][[3]]  ``
``[1] 70 80 90``
``mode( gradebooks[[2]][[3]] )  ``
``[1] "numeric"``
``length( gradebooks[[2]][3] )  ``
``[1] 1``