dplyr:如何获得边际比例的双向表?

时间:2016-10-26 15:16:29

标签: r dplyr

考虑一下

var1<- c('A','B','C','C','G')
var2<- c('G','B','B','F','A')
df = df=data.frame(var1,var2)

> df
  var1 var2
1    A    G
2    B    B
3    C    B
4    C    F
5    G    A

我想在var1var2之间找到一张双向表。

我可以用

> df %>% count(var1,var2) %>% spread(var2, n, fill = 0)
Source: local data frame [4 x 5]
Groups: var1 [4]

    var1     A     B     F     G
* <fctr> <dbl> <dbl> <dbl> <dbl>
1      A     0     0     0     1
2      B     0     1     0     0
3      C     0     1     1     0
4      G     1     0     0     0

或使用table

> table( df$var1, df$var2)

    A B F G
  A 0 0 0 1
  B 0 1 0 0
  C 0 1 1 0
  G 1 0 0 0

两者都给出相同的结果。但现在假设我对行或列比例感兴趣。我可以在这里再次使用table

> prop.table(table( df$var1, df$var2), margin =2) # for column

      A   B   F   G
  A 0.0 0.0 0.0 1.0
  B 0.0 0.5 0.0 0.0
  C 0.0 0.5 1.0 0.0
  G 1.0 0.0 0.0 0.0

> prop.table(table( df$var1, df$var2), margin =1) # for rows

      A   B   F   G
  A 0.0 0.0 0.0 1.0
  B 0.0 1.0 0.0 0.0
  C 0.0 0.5 0.5 0.0
  G 1.0 0.0 0.0 0.0

如何使用dplyr(最短的语法)重现这些?

下面的解决方案似乎有效(仅在一种情况下),虽然我不明白为什么:prop.table(n)函数在这里做了什么?

> df %>%  count(var1,var2) %>% mutate(prop = prop.table(n)) %>% spread(var2, prop, fill = 0)
Source: local data frame [4 x 6]
Groups: var1 [4]

    var1     n     A     B     F     G
* <fctr> <int> <dbl> <dbl> <dbl> <dbl>
1      A     1     0   0.0   0.0     1
2      B     1     0   1.0   0.0     0
3      C     1     0   0.5   0.5     0
4      G     1     1   0.0   0.0     0

此外,在prop.table中使用margin会失败。

> df %>%  count(var1,var2) %>% mutate(prop = prop.table(n ,margin =1)) %>% spread(var2, prop, fill = 0)
Error in eval(substitute(expr), envir, enclos) : 'x' is not an array

谢谢!

3 个答案:

答案 0 :(得分:3)

您可以使用group_by模仿所需的保证金,然后将每个计数除以组中的计数总和(注意,删除列n以避免spread时出现问题:

df %>%
  count(var1,var2) %>%
  group_by(var2) %>%
  mutate(prop = n / sum(n)) %>%
  select(-n) %>%
  spread(var2, prop, fill = 0)

给出

    var1     A     B     F     G
1      A     0   0.0     0     1
2      B     0   0.5     0     0
3      C     0   0.5     1     0
4      G     1   0.0     0     0

答案 1 :(得分:2)

管道真的是一个重要而不是愚蠢的事情:

df %>% with(table(var1, var2)) %>% prop.table(margin=2)

答案 2 :(得分:2)

您也可以在count中反转变量:

res1 <- df %>% count(var1,var2) %>% 
               mutate(prop = prop.table(n)) %>% spread(var2, prop, fill = 0)
##Source: local data frame [4 x 6]
##Groups: var1 [4]
##
##    var1     n     A     B     F     G
##* <fctr> <int> <dbl> <dbl> <dbl> <dbl>
##1      A     1     0   0.0   0.0     1
##2      B     1     0   1.0   0.0     0
##3      C     1     0   0.5   0.5     0
##4      G     1     1   0.0   0.0     0
res2 <- df %>% count(var2,var1) %>% 
               mutate(prop = prop.table(n)) %>% spread(var2, prop, fill = 0)
### A tibble: 4 x 6
##    var1     n     A     B     F     G
##* <fctr> <int> <dbl> <dbl> <dbl> <dbl>
##1      A     1     0   0.0     0     1
##2      B     1     0   0.5     0     0
##3      C     1     0   0.5     1     0
##4      G     1     1   0.0     0     0

解释:正如@a​​listaire在下面的评论中解释的那样:

  

传递向量时,prop.table只是将每个元素除以总和,因此相当于n / sum(n)

此处,count生成对的计数,结果是按group_df的第一个变量输入分组的count。因此,对prop.table的后续调用将按该变量的每个值计算比例。要看到这个:

df %>% count(var1,var2) %>% mutate(prop = prop.table(n))
Source: local data frame [5 x 4]
Groups: var1 [4]  ## Note: grouped by var1

    var1   var2     n  prop
  <fctr> <fctr> <int> <dbl>
1      A      G     1   1.0
2      B      B     1   1.0
3      C      B     1   0.5
4      C      F     1   0.5
5      G      A     1   1.0

df %>% count(var2,var1) %>% mutate(prop = prop.table(n))
Source: local data frame [5 x 4]
Groups: var2 [4]  ## Note: grouped by var2

    var2   var1     n  prop
  <fctr> <fctr> <int> <dbl>
1      A      G     1   1.0
2      B      B     1   0.5
3      B      C     1   0.5
4      F      C     1   1.0
5      G      A     1   1.0