假设我想计算每个组中不同值的比例。例如,使用mtcars数据,我如何计算齿轮数的相对频率由am(自动/手动)与dplyr一步走?

library(dplyr)
data(mtcars)
mtcars <- tbl_df(mtcars)

# count frequency
mtcars %>%
  group_by(am, gear) %>%
  summarise(n = n())

# am gear  n
#  0    3 15 
#  0    4  4 
#  1    4  8  
#  1    5  5 

我想达到的目标:

am gear  n rel.freq
 0    3 15      0.7894737
 0    4  4      0.2105263
 1    4  8      0.6153846
 1    5  5      0.3846154

当前回答

这个答案是基于Matifou的回答。

首先,我修改了它,以确保我不会通过使用scipen选项将freq列作为科学符号列返回。

然后我将答案乘以100以得到一个百分比,而不是小数,以使频率列更容易以百分比的形式阅读。

getOption("scipen") 
options("scipen"=10) 
mtcars %>%
count(am, gear) %>% 
mutate(freq = (n / sum(n)) * 100)

其他回答

试试这个:

mtcars %>%
  group_by(am, gear) %>%
  summarise(n = n()) %>%
  mutate(freq = n / sum(n))

#   am gear  n      freq
# 1  0    3 15 0.7894737
# 2  0    4  4 0.2105263
# 3  1    4  8 0.6153846
# 4  1    5  5 0.3846154

来自dplyr的小插图:

当您按多个变量分组时,每个摘要都会剥离分组的一个层次。这使得逐步上卷数据集变得很容易。

因此,在总结之后,去掉group_by中指定的最后一个分组变量‘gear’。在突变步骤中,数据由剩余的分组变量“am”分组。您可以在每个步骤中用组检查分组。

剥离的结果当然取决于group_by调用中分组变量的顺序。您可能希望执行后续的group_by(am),以使代码更显式。

关于舍入和修饰,请参考@Tyler Rinker的精彩回答。

下面是一个基于R的答案,使用了aggregate和ave:

df1 <- with(mtcars, aggregate(list(n = mpg), list(am = am, gear = gear), length))
df1$prop <- with(df1, n/ave(n, am, FUN = sum))
#Also with prop.table
#df1$prop <- with(df1, ave(n, am, FUN = prop.table))
df1

#  am gear  n      prop
#1  0    3 15 0.7894737
#2  0    4  4 0.2105263
#3  1    4  8 0.6153846
#4  1    5  5 0.3846154 

我们也可以用道具。表,但输出显示不同。

prop.table(table(mtcars$am, mtcars$gear), 1)
   
#            3         4         5
#  0 0.7894737 0.2105263 0.0000000
#  1 0.0000000 0.6153846 0.3846154

你可以使用count()函数,但是根据dplyr版本的不同,它有不同的行为:

Dplyr 0.7.1:返回一个未分组的表:您需要通过am重新分组 Dplyr < 0.7.1:返回一个分组表,因此不需要再次分组,尽管您可能希望为以后的操作取消group()

抑郁症是0.7.1

mtcars %>%
  count(am, gear) %>%
  group_by(am) %>%
  mutate(freq = n / sum(n))

德普林斯

mtcars %>%
  count(am, gear) %>%
  mutate(freq = n / sum(n))

这将生成一个分组表,如果您希望将其用于进一步分析,使用ungroup()删除分组属性可能会很有用。

这个答案是基于Matifou的回答。

首先,我修改了它,以确保我不会通过使用scipen选项将freq列作为科学符号列返回。

然后我将答案乘以100以得到一个百分比,而不是小数,以使频率列更容易以百分比的形式阅读。

getOption("scipen") 
options("scipen"=10) 
mtcars %>%
count(am, gear) %>% 
mutate(freq = (n / sum(n)) * 100)

下面是在dplyr 0.7.1上实现Henrik解决方案的通用函数。

freq_table <- function(x, 
                       group_var, 
                       prop_var) {
  group_var <- enquo(group_var)
  prop_var  <- enquo(prop_var)
  x %>% 
    group_by(!!group_var, !!prop_var) %>% 
    summarise(n = n()) %>% 
    mutate(freq = n /sum(n)) %>% 
    ungroup
}