Some more generalized guidance about navigating R
.
Everything in R is an object
Even whitespace—spaces, tabs and newlines. Objects have properties, such as the names provided in
parameters <- c(k1=2,k2=2,k3=5)
parameters
#> k1 k2 k3
#> 2 2 5
attributes(parameters)
#> $names
#> [1] "k1" "k2" "k3"
attributes(parameters)$names
#> [1] "k1" "k2" "k3"
attributes(parameters)$names[1]
#> [1] "k1"
parameters[attributes(parameters)$names[1]]
#> k1
#> 2
parameters[1]
#> k1
#> 2
parameters["k1"]
#> k1
#> 2
Created on 2023-06-30 with reprex v2.0.2
like @pieterjanvc demonstrated. What this means in terms of objects comes down to how those properties are expressed, which is as a vector of strings just like
c("k1","k2","k3")
In effect, parameters
is twin vectors.
Objects relate to other objects. The most obvious example is objects that are functions. And functions can act on other functions.
sqrt(sqrt(16))
#> [1] 2
Another subtlety is that some objects have as their purpose to delimit other objects.
my_string <- "here it is"
and usually (always?) come in pairs. [
is an object that delimits and it pairs with ]
. In addition it has the property of setting up selection from either a numeric index or a associated name
if there is one. This is what is happening with parameters
. Remember it contains both a numeric vector and a character vector. But those can't coexist in a common vector because a vector must not mix numeric and character. Instead, the two vectors are contained in a list
object. So, using a single pair of bracket accesses the numeric vector in the list and using a pair of double brackets [[
accesses an identified element within that vector.
Lists are a blessing/curse if this syntax is not understood, especially when dealing with objects that are composed of lists of list. Here str()
is a big aid.
fit <- lm(mpg ~ drat,mtcars)
str(fit)
#> List of 12
#> $ coefficients : Named num [1:2] -7.52 7.68
#> ..- attr(*, "names")= chr [1:2] "(Intercept)" "drat"
#> $ residuals : Named num [1:32] -1.42 -1.42 0.763 5.276 2.038 ...
#> ..- attr(*, "names")= chr [1:32] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
#> $ effects : Named num [1:32] -113.65 -22.86 1.05 5.28 2.07 ...
#> ..- attr(*, "names")= chr [1:32] "(Intercept)" "drat" "" "" ...
#> $ rank : int 2
#> $ fitted.values: Named num [1:32] 22.4 22.4 22 16.1 16.7 ...
#> ..- attr(*, "names")= chr [1:32] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
#> $ assign : int [1:2] 0 1
#> $ qr :List of 5
#> ..$ qr : num [1:32, 1:2] -5.657 0.177 0.177 0.177 0.177 ...
#> .. ..- attr(*, "dimnames")=List of 2
#> .. .. ..$ : chr [1:32] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
#> .. .. ..$ : chr [1:2] "(Intercept)" "drat"
#> .. ..- attr(*, "assign")= int [1:2] 0 1
#> ..$ qraux: num [1:2] 1.18 1.09
#> ..$ pivot: int [1:2] 1 2
#> ..$ tol : num 1e-07
#> ..$ rank : int 2
#> ..- attr(*, "class")= chr "qr"
#> $ df.residual : int 30
#> $ xlevels : Named list()
#> $ call : language lm(formula = mpg ~ drat, data = mtcars)
#> $ terms :Classes 'terms', 'formula' language mpg ~ drat
#> .. ..- attr(*, "variables")= language list(mpg, drat)
#> .. ..- attr(*, "factors")= int [1:2, 1] 0 1
#> .. .. ..- attr(*, "dimnames")=List of 2
#> .. .. .. ..$ : chr [1:2] "mpg" "drat"
#> .. .. .. ..$ : chr "drat"
#> .. ..- attr(*, "term.labels")= chr "drat"
#> .. ..- attr(*, "order")= int 1
#> .. ..- attr(*, "intercept")= int 1
#> .. ..- attr(*, "response")= int 1
#> .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv>
#> .. ..- attr(*, "predvars")= language list(mpg, drat)
#> .. ..- attr(*, "dataClasses")= Named chr [1:2] "numeric" "numeric"
#> .. .. ..- attr(*, "names")= chr [1:2] "mpg" "drat"
#> $ model :'data.frame': 32 obs. of 2 variables:
#> ..$ mpg : num [1:32] 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
#> ..$ drat: num [1:32] 3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
#> ..- attr(*, "terms")=Classes 'terms', 'formula' language mpg ~ drat
#> .. .. ..- attr(*, "variables")= language list(mpg, drat)
#> .. .. ..- attr(*, "factors")= int [1:2, 1] 0 1
#> .. .. .. ..- attr(*, "dimnames")=List of 2
#> .. .. .. .. ..$ : chr [1:2] "mpg" "drat"
#> .. .. .. .. ..$ : chr "drat"
#> .. .. ..- attr(*, "term.labels")= chr "drat"
#> .. .. ..- attr(*, "order")= int 1
#> .. .. ..- attr(*, "intercept")= int 1
#> .. .. ..- attr(*, "response")= int 1
#> .. .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv>
#> .. .. ..- attr(*, "predvars")= language list(mpg, drat)
#> .. .. ..- attr(*, "dataClasses")= Named chr [1:2] "numeric" "numeric"
#> .. .. .. ..- attr(*, "names")= chr [1:2] "mpg" "drat"
#> - attr(*, "class")= chr "lm"
Having a feel for the logic helps retain the mechanics of their use.