Zelbinian
Zelbinian

Reputation: 3407

How do I add a list of non-consecutive numbers as an element in a data.frame?

Create a data.frame where a column is a list

^ this got me most of the way there, but there are significant hurdles I can't seem to clear.

Pretend frame is a data.frame of 3 columns with the middle column intended to be a list. This works:

frame[1,]$list_column <- list(1:4)

None of this works:

frame[1,] <- c(1, list(1:4), 3)
frame[1,] <- c(1, I(list(1:4)), 3)
frame[1,]$list_column <- list(1,3,5)
frame[1,]$list_column <- I(list(1,3,5))

In all cases R thinks I'm trying to add multiple things to a bucket that holds 1 thing and I don't know how to tell it otherwise. (And, btw, that last one is the thing I'd really like to do.)

Upvotes: 0

Views: 539

Answers (1)

Stewart Macdonald
Stewart Macdonald

Reputation: 2142

The key is in creating your list correctly:

> list(1:4)
[[1]]
[1] 1 2 3 4
# Produces a list that contains a single vector

> list(1:4, 7:9)
[[1]]
[1] 1 2 3 4

[[2]]
[1] 7 8 9
# Produces a list that contains two separate vectors

> list(c(1:4, 7:9))
[[1]]
[1] 1 2 3 4 7 8 9
# Produces a list that contains a single vector

So you could do something like this:

frame <- data.frame(a=1:3)
frame$list_column <- NA
frame[1,]$list_column <- list(c(1, 3, 5))
frame[2,]$list_column <- list(1:5)
frame[3,]$list_column <- list(c(1:3, 5:9))
print(frame)
  a            list_column
1 1                1, 3, 5
2 2          1, 2, 3, 4, 5
3 3 1, 2, 3, 5, 6, 7, 8, 9

str(frame)
'data.frame':   3 obs. of  2 variables:
 $ a          : int  1 2 3
 $ list_column:List of 3
  ..$ : num  1 3 5
  ..$ : int  1 2 3 4 5
  ..$ : int  1 2 3 5 6 7 8 9

Is that what you're after?

Update to address your other query:

frame <- data.frame(a=rep(NA, 3), b=NA, c=NA)
frame[1,] <- list(list(1), list(c(2,5,7)), list(3))

When you're getting unexpected results, have a look at the structure of the object you're dealing with:

> str(c(1, list(c(2,5,7)), 3))
List of 3
 $ : num 1
 $ : num [1:3] 2 5 7
 $ : num 3

This shows that the second element in the list is a vector with 3 items. If you try to put that into a data frame cell, you'll get an error:

> frame <- data.frame(a=rep(NA, 3), b=NA, c=NA)
> frame[1,] <- c(1, list(c(2,5,7)), 3)
Warning message:
In `[<-.data.frame`(`*tmp*`, 1, , value = list(1, c(2, 5, 7), 3)) :
  replacement element 2 has 3 rows to replace 1 rows

This is telling you the number of elements don't match the number of slots in your data frame.

Upvotes: 1

Related Questions