Search code examples
rlistaggregate

How to "group by" over list elements (in Base R)


Code

list(c(1,2), c('a', 'b'), c('a', 'b'), c(2,3)) -> li
## 
## [[1]]
## [1] 1 2
## 
## [[2]]
## [1] "a" "b"
## 
## [[3]]
## [1] "a" "b"
## 
## [[4]]
## [1] 2 3

Q: Required output as from table().

Factor     c(1,2) c('a', 'b') c(2,3)
Freq           1        2        1 

It looks very elementary, but I cannot find a solution.

Edit - Unfortunately, my list contains ca 500,000 elements. Sorry for not mentioning that. A solution might be to merge the items in the list into a single element:

## 
## [[1]]
## [1] "1 2"
## 
## [[2]]
## [1] "a b"
## 
## [[3]]
## [1] "a b"
## 
## [[4]]
## [1] "2 3"

Then unlist the list and apply table.

Q: How to concatenate the list elements in a single item?

A: sapply(li, paste, collapse = "-") |> table()


Solution

  • unique and match work with lists, so you can match your list to unique members of itself. Call table on the result, then all than remains is to set the names of the result using unique again. This can all be done with the one-liner:

    setNames(table(match(li, unique(li))), unique(li))
    #>    c(1, 2) c("a", "b")     c(2, 3) 
    #>          1           2           1 
    

    Or, if you prefer clarity to brevity, the base R piped equivalent would be:

    li |>
      match(unique(li))    |>
      table()              |>
      setNames(unique(li))
    #>    c(1, 2) c("a", "b")     c(2, 3) 
    #>          1           2           1