Search code examples
rdataframenames

Can a data frame be made to accept alists as rows?


Consider

items<-alist(2^1,2^2,2^3,2^3)

Suppose that I want to construct a data frame where the unevaluated expressions in items are one column and their evaluated versions are in another. In other words, I want something like:

items           results
2^1                   1
2^2                   4
2^3                   8
2^3                   8

as my outputs. I would use the row.names argument, but it rejects duplicated names and cannot be convinced otherwise.

The natural thing to try is

items<-alist(2^1,2^2,2^3,2^3)
outs<-sapply(items,eval)
data.frame(items=items,results=outs)

but the outputs appears to treat each element of the alist as if it were a column name:

> data.frame(items=items,results=outs)
  items.2.1 items.2.2 items.2.3 items.2.3.1 results
1         2         4         8           8       2
2         2         4         8           8       4
3         2         4         8           8       8
4         2         4         8           8       8

lapply does not fair any better:

> outs<-lapply(items,eval)
> data.frame(items=items,results=outs)
  items.2.1 items.2.2 items.2.3 items.2.3.1 results.2 results.4 results.8 results.8.1
1         2         4         8           8         2         4         8           8

I am aware that I could use a matrix instead of a data frame, but that is not what I'm asking about.


Solution

  • @nicola's suggestion in the comment almost works, but doesn't display properly:

    > data.frame(items=I(items),results=vapply(items,eval,1))
        items results
    1 ^, 2, 1       2
    2 ^, 2, 2       4
    3 ^, 2, 3       8
    4 ^, 2, 3       8
    

    If you don't care about the display, I'd use that. If you want it to display nicely, you need to convert the language objects to expression objects, e.g.

    eitems <- lapply(items, as.expression)
    > data.frame(items=I(eitems),results=vapply(items,eval,1))
      items results
    1   2^1       2
    2   2^2       4
    3   2^3       8
    4   2^3       8
    

    or just deparse them to character values if you don't want to be able to evaluate them again:

    ditems <- sapply(items, deparse)
    > data.frame(items = ditems, results=vapply(items,eval,1))
      items results
    1   2^1       2
    2   2^2       4
    3   2^3       8
    4   2^3       8