Question

If I have the following data frame called pets in R:

> pets
     name animal
1     Amy    dog
2     Bob    cat
3   Carol    dog
4   Danny    cat
5 Eustace  horse
6 Frances  horse

I can unstack the data frame to set the animal categories as columns headers like so:

> unstack(pets, pets$name ~ pets$animal)
    cat   dog   horse
1   Bob   Amy Eustace
2 Danny Carol Frances

If, however, the pets data frame only has one instance of each animal:

> pets
     name animal
1     Amy    dog
2     Bob    cat

then running the same code produces this result:

> unstack(pets, pets$name ~ pets$animal)
    res
cat Bob
dog Amy

I need something that puts those animal categories as the column headers, regardless of how many rows fall into each category. Does anyone have any ideas, please?

Was it helpful?

Solution

data.frame and split will do it:

pets <- data.frame(
 name=c("Amy", "Bob", "Carol", "Danny", "Eustace", "Frances"),
 animal=c("dog", "cat", "dog", "cat", "horse", "horse")
)

data.frame(split(pets$name,pets$animal,drop=TRUE))

#    cat   dog   horse
#1   Bob   Amy Eustace
#2 Danny Carol Frances

pets2 <- pets[1:2,]

data.frame(split(pets2$name,pets2$animal,drop=TRUE))

#  cat dog
#1 Bob Amy

OTHER TIPS

You can simply transpose the result:

> t(unstack(pets))
    cat   dog  
res "Bob" "Amy"

If you want a solution that will work for both:

unstack <- function(..., drop=FALSE) {
  u <- utils::unstack(...)
  if (!drop && ncol(u) == 1) {
    u <- t(u)
    rownames(u) <- 1
    return(u)
  } else {
    return(u)
  }
}

This will overwrite the unstack function. drop=TRUE preserves the default behaviour, while drop=FALSE gives you your desired output.

Another alternative:

> p2 <- pets[!duplicated(pets$animal), ]
> data.frame(matrix(p2$name, nrow = 1, ncol = nrow(p2), 
                    dimnames = list(NULL, p2$animal)))
#   dog cat   horse
# 1 Amy Bob Eustace
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top