Assigning NULL to a list element in R?

41,783

Solution 1

Good question.

Check out the R-FAQ:

In R, if x is a list, then x[i] <- NULL and x[[i]] <- NULL remove the specified elements from x. The first of these is incompatible with S, where it is a no-op. (Note that you can set elements to NULL using x[i] <- list(NULL).)

consider the following example:

> t <- list(1,2,3,4)
> t[[3]] <- NULL          # removing 3'd element (with following shifting)
> t[2] <- list(NULL)      # setting 2'd element to NULL.
> t
[[1]]
[2] 1

[[2]]
NULL

[[3]]
[3] 4

UPDATE:

As the author of the R Inferno commented, there can be more subtle situations when dealing with NULL. Consider pretty general structure of code:

# x is some list(), now we want to process it.
> for (i in 1:n) x[[i]] <- some_function(...)

Now be aware, that if some_function() returns NULL, you maybe will not get what you want: some elements will just disappear. you should rather use lapply function. Take a look at this toy example:

> initial <- list(1,2,3,4)
> processed_by_for <- list(0,0,0,0)
> processed_by_lapply <- list(0,0,0,0)
> toy_function <- function(x) {if (x%%2==0) return(x) else return(NULL)}
> for (i in 1:4) processed_by_for[[i]] <- toy_function(initial[[i]])
> processed_by_lapply <- lapply(initial, toy_function)
> processed_by_for
  [[1]]
  [1] 0

  [[2]]
  [1] 2

  [[3]]
  NULL

  [[4]]
  [1] 4

> processed_by_lapply
  [[1]]
  NULL

  [[2]]
  [1] 2

  [[3]]
  NULL

  [[4]]
  [1] 4

Solution 2

Your question is a bit confusing to me.

Assigning null to an existing object esentially deletes that object (this can be very handy for instance if you have a data frame and wish to delete specific columns). That's what you've done. I am unable to determine what it is that you want though. You could try

sampleList[[2]] <- NA

instead of NULL, but if by "I want to lose" you mean delete it, then you've already succeeded. That's why, "The list elements get shifted up."

Solution 3

obj = list(x = "Some Value")
obj = c(obj,list(y=NULL)) #ADDING NEW VALUE
obj['x'] = list(NULL) #SETTING EXISTING VALUE
obj

Solution 4

If you need to create a list of NULL values which later you can populate with values (dataframes, for example) here is no complain:

B <-vector("list", 2) 

a <- iris[sample(nrow(iris), 10), ]
b <- iris[sample(nrow(iris), 10), ]
B[[1]]<-a 
B[[2]]<-b 

The above answers are similar, but I thought this was worth posting.

Share:
41,783
harshsinghal
Author by

harshsinghal

Twig in a Random Forest

Updated on October 10, 2021

Comments

  • harshsinghal
    harshsinghal over 2 years

    I found this behaviour odd and wanted more experienced users to share their thoughts and workarounds. On running the code sample below in R:

    sampleList <- list()
    d<- data.frame(x1 = letters[1:10], x2 = 1:10, stringsAsFactors = FALSE)
    for(i in 1:nrow(d)) {
            sampleList[[i]] <- d$x1[i]
    }
    
    print(sampleList[[1]])
    #[1] "a"
    print(sampleList[[2]])
    #[1] "b"
    print(sampleList[[3]])
    #[1] "c"
    print(length(sampleList))
    #[1] 10
    
    sampleList[[2]] <- NULL
    print(length(sampleList))
    #[1] 9
    print(sampleList[[2]])
    #[1] "c"
    print(sampleList[[3]])
    #[1] "d"
    

    The list elements get shifted up. Maybe this is as expected, but I am trying to implement a function where I merge two elements of a list and drop one. I basically want to lose that list index or have it as NULL.

    Is there any way I can assign NULL to it and not see the above behaviour?

    Thank you for your suggestions.

  • Patrick Burns
    Patrick Burns over 12 years
    This is Circle 8.1.55 of 'The R Inferno' burns-stat.com/pages/Tutor/R_inferno.pdf Circle 8.1.56 is a more subtle version of this.
  • harshsinghal
    harshsinghal over 12 years
    Thank you for the detailed explanation. How does one read the manuals and not overlook these subtleties!!!!