Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Failed to convert a list returned by tapply into a data.frame

I'm doing some data operation with tapply(), and it returns a list-like object. For example:

x <- 1:10
y <- rep(c('A', 'B'), each = 5)
lst.1 <- tapply(x, y, function(vec) return(vec), simplify = FALSE)
lst.1

# $A
# [1] 1 2 3 4 5
# 
# $B
# [1]  6  7  8  9 10

I want to transform it into a data.frame. An intuition is using as.data.frame(), but it failed.

as.data.frame(lst.1)

#             lst1
# A  1, 2, 3, 4, 5
# B 6, 7, 8, 9, 10

I create another list manually to mimic lst.1, and as.data.frame() works as expedted.

lst.2 <- list(A = 1:5, B = 6:10)
lst.2

# $A
# [1] 1 2 3 4 5
# 
# $B
# [1]  6  7  8  9 10

as.data.frame(lst.2)

#   A  B
# 1 1  6
# 2 2  7
# 3 3  8
# 4 4  9
# 5 5 10

What's the difference between lst.1 and lst.2? And how to correctly convert a list returned by tapply (i.e. lst.1) into a data.frame?

like image 924
user18894435 Avatar asked Aug 31 '25 23:08

user18894435


1 Answers

If you take a look at the structure of the list being returned by tapply(), you'll see that it has a dimension attribute and is a list and an array.

str(lst.1)
List of 2
 $ A: int [1:5] 1 2 3 4 5
 $ B: int [1:5] 6 7 8 9 10
 - attr(*, "dim")= int 2
 - attr(*, "dimnames")=List of 1
  ..$ : chr [1:2] "A" "B"

is.array(lst.1)
[1] TRUE

This means when you call as.data.frame() the method being dispatched under the hood is as.data.frame.array() and not as.data.frame.list(). To get around this you can invoke the method you want to use directly:

as.data.frame.list(lst.1) 
  A  B
1 1  6
2 2  7
3 3  8
4 4  9
5 5 10

Or use:

list2DF(lst.1)
  A  B
1 1  6
2 2  7
3 3  8
4 4  9
5 5 10
like image 194
Ritchie Sacramento Avatar answered Sep 03 '25 14:09

Ritchie Sacramento