Count the number of times each string occurs in R

r, string

Solution

There are quite a few ways to do this. In base R this can be done using `table()` (as mentioned under comment) and also shown below:

set.seed(1L)
x <- sample(paste0("V", 1:10), 1e3, TRUE)

table(x)
# x
#  V1 V10  V2  V3  V4  V5  V6  V7  V8  V9 
#  96 110 104  93 112 115  86  90 106  88 

However, there are two things here: 1) It automatically sorts the result based on the input strings, which may not be always desirable. 2) If you've a large vector and/or looking for speed, then it may not be the way to go, as it doesn't seem to scale well.

Here's an example on point (2):

set.seed(1L)
x <- sample(paste0("V", 1:1e4), 1e8, TRUE)
system.time(table(x))
#   user  system elapsed 
# 26.899   6.827  36.826 

The `data.table` package retains the input order while providing counts and is at the same time very fast. Here's the runtime on the same vector using `data.table`:

require(data.table)     ## >= 1.9.0
dt <- setDT(list(x=x))  ## create a data.table

system.time(ans1 <- dt[, .N, by=x]) ## get counts
#  user  system elapsed 
# 4.795   0.979   5.839

If you do want to obtain the results sorted, you can just do: `setkey(ans1, x)` which'll sort the result by column 'x' from `ans1`, once again this is extremely fast in `data.table`.

system.time(setkey(ans1, x))
#  user  system elapsed 
# 0.002   0.000   0.003 

Here's also a comparison on speed with `dplyr`'s `data.frame` method for those interested - note that this does not preserve the input order (sorts by default), like `table()` from base as well.

require(dplyr)                  ## Commit 1362 from github
df <- tbl_df(as.data.frame(dt)) ## get tbl_df object

system.time(ans2 <- df %.% group_by(x) %.% summarise(n()))
#   user  system elapsed 
# 15.983   1.318  17.807 

HTH

Problem

Given a list of strings, how do I get a count of how many times each occurs? Say I've a vector `x` as follows: ``` x <- c('cat','cat','cat','cat','dog','dog','cat','cow') ``` I'd like to get the counts as: ``` # cat : 5 # dog : 2 # cow : 1 ``` I know the answer won't be formatted like this but something along those lines.

Original source