Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

For each `pop` get frequencies of the elements of `id`

Tags:

r

data.table

Consider this data:

m = data.frame(pop=c(1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4),
                id=c(0,1,1,1,1,1,0,2,1,1,1,2,1,2,2,2))

> m
   pop id
1    1  0
2    1  1
3    1  1
4    1  1
5    2  1
6    2  1
7    2  0
8    2  2
9    2  1
10   3  1
11   3  1
12   3  2
13   3  1
14   3  2
15   4  2
16   4  2

I would like to get the frequency of each unique id in each unique pop? For example, the id 1 is present 3 times out of 4 when pop == 1, therefore the frequency of id 1 in pop 1 is 0.75.

I came up with this ugly solution:

out = matrix(0,ncol=3)

for (p in unique(m$pop))
{
    for (i in unique(m$id))
    {
        m1  = m[m$pop == p,]
        f   = nrow(m1[m1$id == i,])/nrow(m1)
        out = rbind(out, c(p, f, i))
    }
}
out = out[-1,]
colnames(out) = c("pop", "freq", "id")

# SOLUTION

> out
      pop freq id
 [1,]   1 0.25  0
 [2,]   1 0.75  1
 [3,]   1 0.00  2
 [4,]   2 0.20  0
 [5,]   2 0.60  1
 [6,]   2 0.20  2
 [7,]   3 0.00  0
 [8,]   3 0.60  1
 [9,]   3 0.40  2
[10,]   4 0.00  0
[11,]   4 0.00  1
[12,]   4 1.00  2

I am sure there exists a more efficient solution using data.table or table but couldn't find it.

like image 767
Remi.b Avatar asked Dec 02 '25 23:12

Remi.b


2 Answers

Here's what I might do:

as.data.frame(prop.table(table(m),1))
#    pop id Freq
# 1    1  0 0.25
# 2    2  0 0.20
# 3    3  0 0.00
# 4    4  0 0.00
# 5    1  1 0.75
# 6    2  1 0.60
# 7    3  1 0.60
# 8    4  1 0.00
# 9    1  2 0.00
# 10   2  2 0.20
# 11   3  2 0.40
# 12   4  2 1.00

If you want it sorted by pop, you can do that afterwards. Alternately, you could transpose the table with t before converting to data.frame; or use rev(m) and prop.table on dimension 2.

like image 89
Frank Avatar answered Dec 04 '25 13:12

Frank


Try:

library(dplyr)
m %>% 
  group_by(pop, id) %>% 
  summarise(s = n()) %>%
  mutate(freq = s / sum(s)) %>%
  select(-s)

Which gives:

#Source: local data frame [8 x 3]
#Groups: pop
#
#  pop id freq
#1   1  0 0.25
#2   1  1 0.75
#3   2  0 0.20
#4   2  1 0.60
#5   2  2 0.20
#6   3  1 0.60
#7   3  2 0.40
#8   4  2 1.00
like image 30
Steven Beaupré Avatar answered Dec 04 '25 15:12

Steven Beaupré



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!