如何构建自定义函数以根据另一个因素获取一个因素的频率?

How can I build a custom function to get the frequencies of one factor depending on another factor?

我有一个包含大量因素的数据集,我想根据另一个因素获得每个因素的相对频率。例如,让我们使用 mtcars:

mtcars$am <- as.factor(mtcars$am)
mtcars$cyl <- as.factor(mtcars$cyl)

我想根据 cyl 的值获取 am == 1 的频率。在这种情况下,我应该得到三个相对频率,因为 cyl 具有三个级别(4、6 和 8)。我有这个代码工作:

mtcars %>%
  select(am, cyl) %>%
  table(.) %>% 
  prop.table(., 1) %>% 
  round(., digits = 2) %>% 
  data.frame() %>% 
  filter(am == 1) %>% 
  t() %>% 
  data.frame() %>% 
  slice(3)

# # A tibble: 1 x 3
#       X1     X2     X3
#   <fctr> <fctr> <fctr>
# 1   0.62   0.23   0.15

如果你运行它,你会得到上面的三个频率。当然,我构建了这段代码,所以我知道 X1 对应于 cyl == 4 的频率,X2 是 cyl == 6,X3 是 cyl == 8。

现在,我想用大量因子(其他二元因子,如 am)来做到这一点。所以,我想构建一个自定义函数,稍后将所有频率绑定为行,并使用这些频率创建一个漂亮的 table。现在,我有这个:

pull_freq <- function(mydata, var1, var2){      
 require(tidyverse)   
  var1 <- enquo(var1)
  var2 <- enquo(var2)
  mydata %>%
    select(!!var1, !!var2) %>%
    table(.) %>% 
    prop.table(., 1) %>% 
    round(., digits = 2) %>% 
    data.frame() %>% 
    filter(!!var1 == 1) %>% 
    t() %>% 
    data.frame() %>% 
    slice(3)
}

pull_freq(mtcars, am, cyl)

# A tibble: 1 x 0

但是如您所见,当我 运行 这个函数时,我没有得到任何输出。关于为什么我没有得到任何输出的任何想法?我怎样才能让这个功能发挥作用?谢谢!

也许我完全离开了,但就是这样吗?

data(mtcars)

agg <- aggregate(mtcars$cyl, list(mtcars$cyl, mtcars$am), FUN = length)
names(agg) <- c("cyl", "am", "count")

agg$freq <- ave(agg$count, agg$am, FUN = function(x) x/sum(x))
agg <- t(agg[-3])
agg

请注意,我没有将 cylam 强制转换为 as.factor 的因数。这是因为当转置数据帧时,结果将是 matrix。由于矩阵只能有一个 class 的元素,所有的值都会变成 class characterfreq 值将不再是数字。

自定义函数

myfun <- function(df, col1, col2, col3) {
            require(dplyr)
            require(tidyr)
            col1 <- enquo(col1)
            col2 <- enquo(col2)
            df %>% 
              count(!!col1, !!col2) %>% 
              group_by(!!col1) %>%
              mutate(tot = sum(n)) %>%
              ungroup() %>%
              group_by(!!col2) %>% 
              mutate(n = n / tot) %>%
              select(-tot) %>% 
              filter(UQ(col1)==1) %>%
              spread_(col3, "n") %>%
              round(., digits=2)
        }

输出

myfun(mtcars, am, cyl, "cyl")

# am    `4`   `6`   `8`
#  1  0.62  0.23  0.15

这个怎么样,

library(tidyverse)
getFreq <- function(data, group_var, value_var) {
    data %>%
        group_by_(group_var) %>%
        do({
            table(.[[value_var]]) %>%
                prop.table() %>%
                as_tibble()
        }) %>%
        spread(Var1, n)
}

getFreq(mtcars, "am", "cyl") %>% print()

您可以在之后进行所有过滤,或者只包含在函数中。