-1

Sometimes I just want to feed indices or labels into a map* type function, especially in problems where the easiest solution is to enumerate all possible combinations. So, I write an expression like this

x = expand.grid(paste0("A", 1:10), paste0("B", 1:10))

  Var1 Var2
1   A1   B1
2   A2   B1
3   A3   B1
4   A4   B1
5   A5   B1
6   A6   B1

Now, now I want to convert each row to a list with an ugly hack like

data.frame(t(x))

Or do something like this, which is annoying since the output is a nested list, and requires another lapply to fix.

apply(x, 1, list) then lapply(.Last.value, unlist)

There has to be a more elegant way of doing this right?

Sandipan Dey
  • 21,482
  • 2
  • 51
  • 63
Vlo
  • 3,168
  • 13
  • 27

1 Answers1

1

If x is a matrix as titled for the question, I don't think it's a bad idea by doing data.frame(t(x)). On the other hand, if it is a data frame as generated by expand.grid, you can use the transpose function from data.table package, this is superior to t(x) because t() coerce the data frame to matrix which changes the underlying storage mode of the data and changes it back to a data frame which could be very inefficient, while transpose is designed for lists, data frames or data tables transposing as from ?transpose:

transpose is an efficient way to transpose lists, data frames or data tables.

Here is some benchmark about transposing a data frame:

microbenchmark::microbenchmark(data.frame(t(x)), data.table::transpose(x), split(x, 1:nrow(x)), lapply(apply(x, 1, list), unlist), times = 10)

# Unit: milliseconds
#                               expr        min         lq       mean     median         uq        max neval
#                   data.frame(t(x)) 114.061549 117.662053 121.628102 120.812289 125.132211 135.421358    10
#           data.table::transpose(x)   1.146525   1.400207   1.469908   1.467571   1.623157   1.736432    10
#                split(x, 1:nrow(x)) 160.550576 161.626339 187.385706 167.800102 179.647717 355.913319    10
#  lapply(apply(x, 1, list), unlist)   8.183313   8.379791   9.317694   8.783287   9.883049  12.345740    10
Psidom
  • 209,562
  • 33
  • 339
  • 356