Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rename a component of R lists

l1 <- list(a = 'FirstComponent', b= 'SecondComponent')

To rename the first component from a to c I can do this:

names(l1) <- c('c', 'b')

Or this:

names(l1)[1] <- c('c')

But not this:

names(l1[1]) <- c('c')

Nor this:

names(l1[[1]]) <- c('c')

Why wouldn't the third and fourth code example work? They also try to rename an R object l1[1] and l1[[1]]. What's happening behind the scene?

=========Following is part of the original question===========

R documentation: it is possible to update just part of the names attribute via the general rules: see the examples. This works because the expression there is evaluated as z <- "names<-"(z, "[<-"(names(z), 3, "c2")).

The returned value of names(z) in "[<-"(names(z), 3, "c2") is passed to the next function as a parameter, which is "[<-".

like image 396
Ryan Avatar asked Dec 11 '25 07:12

Ryan


1 Answers

You are looking at three different functions: <-, [<- and names<-. What is happening will be clear once you understand what each of these does.

The assignment operator <- takes two arguments, a variable name and value, and assigns the value to that variable. So `<-`(x, 'y') has the same effect as x <- 'y'.

[<- can take many arguments, but the ones you are interested in are the variable, the index, and the value. It assigns the value specified to the index of the vector stored in the variable and returns the result. So for example if a <- c(1, 2, 3), then `[<-`(a, 2, 10) will return (a copy of) the vector a, having replaced its second entry with 10.

names<- is a function which takes two arguments, a list and a vector of names, and assigns these names to the list. So `names<-`(l1, c('a', 'b')) is just another way of writing names(l1) <- c('a', 'b').

What the documentation is telling you, is how the function names<- is defined, based on the definition of [<-. What happens in z <- `names<-`(z, `[<-`(names(z), 3, "c2")) is:

  1. Start e.g. with z = list('a' = 1, 'b' = 2, 'c' = 3). First, get the names of z:

    nz <- names(z)  # c("a", "b", "c") 
    
  2. Replace the 3rd entry of nz with "c2" and return the result

    nznew <- `[<-`(nz, 3, "c2")  # c("a", "b", "c2")
    
  3. Replace the names of z with nznew and return the result

    z <- `names<-`(z, nznew)
    

Why does names(l1[1]) <- 'c' not work? It actually does, but it does not replace the first element of the list. When you call l1[1], its value is returned into a new variable (which is a list consisting only of the first component of l1) and then the names of that variable are modified (but not assigned to anything!). Try for example

x <- l1[1]
names(x) <- 'c'

and see how the names of x have changed. Or, in one step, x <- `names<-`(l1[1], 'c').

Why does names(l1[[1]]) <- 'c' not work? Well, same reason as above, plus l1[[1]] actually returns the contents of the first element of l1 which may not even have a names attribute.

like image 135
konvas Avatar answered Dec 13 '25 21:12

konvas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!