Element calculation in a vector

Hi, I have a question with element calculation in a vector, I would like to understand why I need to use "as.vector" in the calculation in order to get a right output for x, and why the previous one called "x.k1"
I think this must be a very basic question, but I cannot identify key words to google the answer, so you can even give me a book link to elaborate on calculation for elements in vector/matrix/data.frame

Thanks

parameters <- c(k1=2,k2=2,k3=5)
initials <- c(P = 3,
x = parameters["k1"]*parameters["k2"])
x
#> Error in eval(expr, envir, enclos): object 'x' not found
initials
#> P x.k1
#> 3 4
initials <- c(P = 3,
x = as.vector(parameters["k1"]*parameters["k2"]))
initials
#> P x
#> 3 4

Hi,

Welcome to the RStudio community!

Your issue stems from the rather complicated way R uses named lists or vectors and how to access them. Below is an overview of all the steps that should explain this in a bit more detail

parameters <- c(k1=2,k2=2,k3=5)

#Get the name + value (single brackets)
parameters["k1"]
#> k1 
#>  2
#Get the value only (double brackets)
parameters[["k1"]]
#> [1] 2
#Ways to remove names 
unname(parameters)
#> [1] 2 2 5
as.vector(parameters)
#> [1] 2 2 5

#The first name will be kept if single brackets are used
parameters["k1"]*parameters["k2"]
#> k1 
#>  4

#When creating a new named list using named values, new and old names will be merged with a .
#In this case x.k1
initials <- c(P = 3, x = parameters["k1"]*parameters["k2"])
initials
#>    P x.k1 
#>    3    4

#Avoid this by only using values
initials <- c(P = 3, x = parameters[["k1"]]*parameters[["k2"]])
initials
#> P x 
#> 3 4

Created on 2023-06-30 with reprex v2.0.2

Hope this helps,
PJ

4 Likes

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.

2 Likes

This topic was automatically closed 42 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.