aeliv002 aeliv002 - 3 months ago 22
R Question

R split hierarchical list of lists

I have a list of lists. I want to split this list into two list.
It is better to explain in example. So here is example.

List consist of 3 lists.
Each of the list element is a list of 2 data.frames. (person, car)

> df1 = data.frame(id = 1, name = "John")
> df2 = df1
> df3 = df1
> df4 = data.frame(id = 1, car = "Opel")
> df5 = df4
> df6 = df5
> list1 = list(person = df1,car=df4)
> list2 = list(person = df2,car=df5)
> list3 = list(person = df3,car=df6)
> listMain = list(list1,list2,list3)
> str(listMain)
List of 3
$ :List of 2
..$ person:'data.frame': 1 obs. of 2 variables:
.. ..$ id : num 1
.. ..$ name: Factor w/ 1 level "John": 1
..$ car :'data.frame': 1 obs. of 2 variables:
.. ..$ id : num 1
.. ..$ car: Factor w/ 1 level "Opel": 1
$ :List of 2
..$ person:'data.frame': 1 obs. of 2 variables:
.. ..$ id : num 1
.. ..$ name: Factor w/ 1 level "John": 1
..$ car :'data.frame': 1 obs. of 2 variables:
.. ..$ id : num 1
.. ..$ car: Factor w/ 1 level "Opel": 1
$ :List of 2
..$ person:'data.frame': 1 obs. of 2 variables:
.. ..$ id : num 1
.. ..$ name: Factor w/ 1 level "John": 1
..$ car :'data.frame': 1 obs. of 2 variables:
.. ..$ id : num 1
.. ..$ car: Factor w/ 1 level "Opel": 1


I want to split this list into two lists.
First one should be personList, second is carList. Like this.

> listPerson <- list(df1,df2,df3)
> str(listPerson)
List of 3
$ :'data.frame': 1 obs. of 2 variables:
..$ id : num 1
..$ name: Factor w/ 1 level "John": 1
$ :'data.frame': 1 obs. of 2 variables:
..$ id : num 1
..$ name: Factor w/ 1 level "John": 1
$ :'data.frame': 1 obs. of 2 variables:
..$ id : num 1
..$ name: Factor w/ 1 level "John": 1
> listCars <- list(df4,df5,df6)
> str(listCars)
List of 3
$ :'data.frame': 1 obs. of 2 variables:
..$ id : num 1
..$ car: Factor w/ 1 level "Opel": 1
$ :'data.frame': 1 obs. of 2 variables:
..$ id : num 1
..$ car: Factor w/ 1 level "Opel": 1
$ :'data.frame': 1 obs. of 2 variables:
..$ id : num 1
..$ car: Factor w/ 1 level "Opel": 1


How to do that?
Thanks in advance.

Answer

You can use lapply to go through each element in listMain and extract the first (second) element. I think the key point here is the use of [[ like any "traditional" function in lapply.

listPerson <- lapply(listMain, `[[`, 1)
listCar <- lapply(listMain, `[[`, 2)

As @Frank suggests in the comment, you can subset by name as well. The key point remains that you can use [[ like regular function.

listPerson <- lapply(listMain, `[[`, "person")

To read the docs for this function, type ?`[[`.

Comments