rg4s
rg4s

Reputation: 897

How to export values from the list of lists into a data frame?

I have a very complicated structure, see pic below. I am struggling with this problem for a long time, and I really need help.

enter image description here

Here's the sample code to make my question more reproducible

t <- list(
list(answers = list(list(values = "male"),
                   list(values = "6"),
                   list(values = "9"),
                   list(values = "9"),
                   list(values = "other"))
 ),
list(answers = list(list(values = "145")
                  )
)

What I need are the values which are in the answers (from the each list).

I need this to look like a data frame — each list is the column (variable) and each value of the 1st list in answers is, obviously, value. Like this

> d <- data.frame("1" = "male", "2" = 6,
+                 "3" = 9, "4.1" = 9,
+                 "4.2" = 8,
+                 "5" = "other",
+                 "6" = 145)
> d

    X1 X2 X3 X4  X5   X6
1 male 6  9  9  other 145

The other issue is that values in the 1st list of answers can contain multiple values. And I really do not know how to deal with it as I need to assign variables their values accurately.

So, I cannot imagine how to get this. Intuitively, I think that lapply() may help me, but I do not know how to use it properly.

Upvotes: 0

Views: 77

Answers (2)

Paul van Oppen
Paul van Oppen

Reputation: 1495

Tricky one. Here are my thoughts. Also, not so helpful to not provide a dput of your data.

First I have to recreate a data set that resembles yours (extra work for me):

test <- list(
  list(
    answers = list(
      values = list("6", "8", "4", "11", "18"),
      question = list("some_text_1", "some_text_2", "some_text_3"))
    ),
  list(
    answers = list(
      values = list("male"),
      question = list("some_text_4", "some_text_5", "some_text_6"))
  )
  )
)

With some effort I can do this:

l1 <- lapply(test, function(x) lapply(x,`[[`, 1))
l2 <- unlist(l1, recursive = FALSE)
l3 <- unlist(l2, recursive = FALSE)

With this result:

> l3
$answers1
[1] "6"

$answers2
[1] "8"

$answers3
[1] "4"

$answers4
[1] "11"

$answers5
[1] "18"

$answers
[1] "male"

Or simpler:

unlist(l1)

But the latter looses structure and all values vectors end up as a single character vector. In your list, I think this would give you all the values vectors at the 3rd nested level as a list with elements of unequal length. Because your values vectors have unequal length I would probably not try to coerce this to a data frame. Is this close enough?

UPDATE

With the update in the data set we can now do:

l1 <- lapply(t, `[[`, 1)
l2 <- unlist(l1, recursive = FALSE)
df <- as.data.frame(l2)

with this output:

> df
  values values.1 values.2 values.3 values.4 values.5
1   male        6        9        9    other      145

Upvotes: 2

Gregor Thomas
Gregor Thomas

Reputation: 145775

Using your sample data:

results = unlist(lapply(t, "[[", "answers"))
names(results) = paste0("X", seq_along(results))
results = as.data.frame(t(results))
#     X1 X2 X3 X4    X5  X6
# 1 male  6  9  9 other 145

The numbers are class character here, you may want to use type.convert(results) which will convert them to numerics (though it will also convert the remaining strings to factors).

Upvotes: 2

Related Questions