Home > Net >  How to keep new elements of a list on the same level in R
How to keep new elements of a list on the same level in R

Time:12-10

I am trying to do several analyses on datasets that are in a list in R. I have to generate information about each data set in a list, and then based on that new information, generate another set of information. What I've been finding is that when I conduct these calculations, the "data" is clustering within itself repeatedly, and this gets worse as I do more and more calculations. How can I prevent this kind of clustering? I have provided an example below of this phenomenon, but want to note that this analysis, in terms of is.numeric() and is.character(), is not similar to what I am doing.

lat_1 <- c(23.2, 14.5, 28.6)
lon_1 <- c(12.1, 8.5, 2.2)

lat_2 <- c(89.3, 94.4, 72.3)
lon_2 <- c(45.2, 47, 48.5)

coords_1 <- data.frame(lon_1, lat_1)
coords_2 <- data.frame(lon_2, lat_2)

list_coords <- list(coords_1, coords_2)

list_coords_2 <- lapply(list_coords, function(m) {
  list(data = m, numeric_answer = is.numeric(m) )
})

And this is the structure I like, where the original data (data) and the newly created "numeric_answer" are on the same level:


str(list_coords_2)

#Output:

 $ :List of 2
  ..$ data          :'data.frame':  3 obs. of  2 variables:
  .. ..$ lon_1: num [1:3] 12.1 8.5 2.2
  .. ..$ lat_1: num [1:3] 23.2 14.5 28.6
  ..$ numeric_answer: logi FALSE

However, when I try to add another object to this list, the new data, "another_part", is on a different level than "numeric answer":


list_coords_3 <- lapply(list_coords_2, function(m) {
  list(data = m, another_part = is.character(m))
})

str(list_coords_3)

#Output:

List of 2
 $ :List of 2
  ..$ data        :List of 2 
  .. ..$ data          :'data.frame':   3 obs. of  2 variables:
  .. .. ..$ lon_1: num [1:3] 12.1 8.5 2.2
  .. .. ..$ lat_1: num [1:3] 23.2 14.5 28.6
  .. ..$ numeric_answer: logi FALSE
  ..$ another_part: logi FALSE
 $ :List of 2
  ..$ data        :List of 2
  .. ..$ data          :'data.frame':   3 obs. of  2 variables:
  .. .. ..$ lon_2: num [1:3] 45.2 47 48.5
  .. .. ..$ lat_2: num [1:3] 89.3 94.4 72.3
  .. ..$ numeric_answer: logi FALSE
  ..$ another_part: logi FALSE

It is necessary that it rather all comes out like this:


 $ :List of 2
  ..$ data          :'data.frame':  3 obs. of  2 variables:
  .. ..$ lon_1: num [1:3] 12.1 8.5 2.2
  .. ..$ lat_1: num [1:3] 23.2 14.5 28.6
  ..$ numeric_answer: logi FALSE
  ..$ another_part: logi FALSE

CodePudding user response:

I would do this to add another_part to your list.

You don't need to wrap m in a list(). Since m is already the list element, you are nesting another list inside of it. Instead assign directly to m.

list_coords_3 <- lapply(list_coords_2, function(m) {
  # do your calculation on m then assign the result to another_part
  m$another_part = FALSE
  return(m)
})
List of 2
 $ :List of 3
  ..$ data          :'data.frame':  3 obs. of  2 variables:
  .. ..$ lon_1: num [1:3] 12.1 8.5 2.2
  .. ..$ lat_1: num [1:3] 23.2 14.5 28.6
  ..$ numeric_answer: logi FALSE
  ..$ another_part  : logi FALSE
 $ :List of 3
  ..$ data          :'data.frame':  3 obs. of  2 variables:
  .. ..$ lon_2: num [1:3] 45.2 47 48.5
  .. ..$ lat_2: num [1:3] 89.3 94.4 72.3
  ..$ numeric_answer: logi FALSE
  ..$ another_part  : logi FALSE

CodePudding user response:

you could Map the original list like:

list_coords |>
Map(f = \(m) list(data = m, 
                  numeric_answer = is.numeric(m),
                  another_part = is.character(m)
                  )
    )

Map is a base R function. Package {purrr} offers a variety of convenient helpers for list manipulation.

  • Related