Ambitious Intern
Ambitious Intern

Reputation: 341

How to store vector in dataframe in R

I am trying to create a dataframe through a for loop and trying to add a vector for each row of the data frame.

The rows are people and the columns are the name category and points category.

For example I'm trying to have something like...

Name  Points
Susie c(12,45,23)
Bill  c(13,24,12,89)
CJ    c(12)

So far my code looks like

names_list <-c("Susie","Bill","CJ")
result = data.frame()

for (name in names_list){
    listing = .....
    frame = data.frame(name,listing)
    names(frame) = c("name","list")
    result <- rbind(result,frame)
}

Where listing happens to be the points associated with that name. However instead of creating 1 row for each name containing all their points, it creates multiple rows with the same name for each point.

Result looks like

1 Susie    12
2 Susie    45
3 Susie    23
4  Bill    13
5  Bill    24
6  Bill    12
7  Bill    89
8    CJ    12

Upvotes: 8

Views: 26500

Answers (3)

Bastiaan Quast
Bastiaan Quast

Reputation: 3535

Name   <- c("Suzie", "Bill", "CJ")
Points <- list(c(   12,45,23),
               c(13,24,12,89),
               c(         12)
           )
result <- as.data.frame(cbind(Name, Points))

Then:

print(result)

Gives:

> result
   Name         Points
1 Suzie     12, 45, 23
2  Bill 13, 24, 12, 89
3    CJ             12

Note:

print(result$Points)

Gives:

> result$Points
[[1]]
[1] 12 45 23

[[2]]
[1] 13 24 12 89

[[3]]
[1] 12

Upvotes: 0

Ista
Ista

Reputation: 10437

The specific problem you've encountered is due to data.frame flattening any list inputs. This can be prevented using the identify function I. For example,

data.frame(a = 1, b = list(c("a", "b")))

doesn't do what you want, but

data.frame(a = 1, b = I(list(c("a", "b"))))

does. A discussion of this behavior and some alternatives are available at http://r4ds.had.co.nz/many-models.html#list-columns-1

You can use I to produce the desired result using your example as well:

names_list <-c("Susie","Bill","CJ")
points <- list(c(12,45,23),
               c(13,24,12,89),
               12)

result = data.frame()

for (i in 1:length(names_list)){
    frame = data.frame(names_list[[i]], I(points[i]))
    names(frame) = c("name","list")
    result <- rbind(result,frame)
}

though as pointed out in the comments, there are better ways to do it. All you really need is

data.frame(
    name = names_list,
    points = I(points))

Upvotes: 12

UpsideDownRide
UpsideDownRide

Reputation: 558

I don't know in what structure your vector value sare but in general to nest vectors in a column you can do something like this:

names <- c("A", "B", "C")
vectors <- list(list(1,2,3), list(4,5,6), list(7,8,9))
as.data.frame(cbind(names, vectors))

   names vectors
 1     A 1, 2, 3
 2     B 4, 5, 6
 3     C 7, 8, 9

Upvotes: 3

Related Questions