Home > Back-end >  Problems with Lists in R
Problems with Lists in R

Time:03-23

I am a little bit puzzled when using lists of lists. If I try the following code, I get an error and I don't understand why:

library(tibble)

data <- list()
data[1][[1]] <- tibble(year = rep(2010,4)) # works
data[1][[2]] <- tibble(year = rep(2011,4)) # gives me an error

# Warning message:
#   In data[1][[2]] <- tibble(year = rep(2011, 4)) :
#   number of items to replace is not a multiple of replacement length

Any help on this, would be appreciated.

CodePudding user response:

Try this:

data <- list()
data[[1]] = list()
data[[1]][[1]] <- tibble(year = rep(2010,4))
data[[1]][[2]] <- tibble(year = rep(2011,4))

output:

[[1]]
[[1]][[1]]
# A tibble: 4 × 1
   year
  <dbl>
1  2010
2  2010
3  2010
4  2010

[[1]][[2]]
# A tibble: 4 × 1
   year
  <dbl>
1  2011
2  2011
3  2011
4  2011

CodePudding user response:

If you want a list of tibbles you index like this.

data <- list()

data[1][[1]] <- tibble(year = rep(2010,4))
data[2][[1]] <- tibble(year = rep(2011,4))


str(data)

# List of 2
#  $ : tibble [4 x 1] (S3: tbl_df/tbl/data.frame)
#   ..$ year: num [1:4] 2010 2010 2010 2010
#  $ : tibble [4 x 1] (S3: tbl_df/tbl/data.frame)
#   ..$ year: num [1:4] 2011 2011 2011 2011

CodePudding user response:

The error happens because data[1][[2]] <- tibble(year = rep(2011, 4)) attempts to add a new column year to the tibble it obtained by running data[1]. It is generally advisable to use double brackets when working with lists.

To illustrate why, see the output of the following code:

l <- list()
l[1] <- tibble(year = rep(2010,4))
l
[[1]]
[1] 2010 2010 2010 2010

# subsetting with [1] can be surprising
l[1][1][1][1][1][1][1]
[[1]]
[1] 2010 2010 2010 2010

a tidyverse-like way to construct such nested list, avoiding repetition in code, would be

#using tidyverses' purrr package
data <- list(purrr::map(2010:2011, ~ tibble(year = rep(.x, 4))))

An alternative, which one should be wary off, see the second circle of R Inferno on growing objects, is to properly initialize a list, and then populate it.

# initialize, then fill
data <- list(rep(list(NULL), 2))
data[[1]][[1]] <- f(2010)
data[[1]][[2]] <- f(2011)
  •  Tags:  
  • r
  • Related