4

I'm looking for a efficient way for the following transformation:

Example input:

ob <- list(a = 2, b = 3)

Expected output:

  key value
1   a     2
2   b     3

Current (verbose) solution:

data.frame(key = names(ob), value = unlist(ob, use.names = FALSE))
markus
  • 25,843
  • 5
  • 39
  • 58
s_baldur
  • 29,441
  • 4
  • 36
  • 69

1 Answers1

6

Try stack

stack(ob)
#  values ind
#1      2   a
#2      3   b

You would need to change the names though. Use setNames

setNames(stack(ob), nm = c("value", "key"))

benchmark

Addressing @Roland's comment, stack seems to be more efficient indeed. please don't use stack but OP's solution for efficiency reasons.

n <- 1e5
lst <- as.list(seq_len(n))
names(lst) <- paste0("a", seq_len(n))

library(microbenchmark)
benchmark <- microbenchmark(
  snoram = snoram(lst),
  markus = markus(lst), times = 50
)
benchmark
#Unit: milliseconds
#   expr      min       lq     mean   median       uq      max neval
# snoram   2.475258   2.594479   2.739639   2.652843   2.715575   5.92216    50
# markus 114.387692 119.028200 134.745626 137.524606 144.045112 162.11510    50

Functions used (so far)

snoram <- function(l) {
  data.frame(key = names(l), value = unlist(l, use.names = FALSE),
             stringsAsFactors = FALSE) # this gives a hugh performance gain
                                       # thanks to @Roland
}

markus <- function(l) {
  setNames(stack(l), nm = c("value", "key"))
}
markus
  • 25,843
  • 5
  • 39
  • 58