遍历按列变量分组的函数

时间:2019-10-04 12:15:33

标签: r dplyr

我有一个数据集,其中的列格式为Bal,Q,W,E,R,T,Y。 我编写了一个函数,可以根据自己选择的列进行总结。

BandFunction <- function(x, y){ y <- enquo(y)
    return(x %>%
    group_by(!!y) %>% 
    summarise(Vol=n(),
              Bal = sum(Bal)) %>% 
      mutate(
             'Vol %' = Vol/sum(Vol),
             'Bal %' = Bal/sum(Bal)
      )
    )
    }

我希望遍历此功能以制作多个数据集。我尝试了以下方法;

Cols <- c("Q", "W", "E","R","T","Y")
ListofDFs <- list()
for(i in 1:length(Col)){
        ListofDFs[[i]] <- BandFunction(df, Cols[i])}
    return(ListofDFs)
        }

但是不起作用,因为它将产生data.frames,其列标题为Cols[i]

3 个答案:

答案 0 :(得分:2)

这是您解决此问题的方式

我用{{ y }}更改了您的功能(没关系,也可以使用enquo(y))。

BandFunction <- function(x, y){ 
return(x %>%
         group_by({{y}}) %>% 
         summarise(Vol=n(),
                   Bal = sum(mpg)) %>% 
         mutate(
           'Vol %' = Vol/sum(Vol),
           'Bal %' = Bal/sum(Bal)
         )
)
}

创建一个您关心的变量列表(在您的情况下,这是QWERTY向量)

my_vars <- names(mtcars)[2:3]

## check my_vars %>% syms()

my_vars %>%
# The syms command is key to generate a list of columns to loop over
  syms() %>%
# now call and don't forget to use !!var
# otherwise you are asking for the column `var` to get evaluated
  purrr::map(function(var) BandFunction(mtcars, !!var))

请注意,我正在使用mtcarsmpg来获得可重复的示例。根据您的目的进行更改

结果是

[[1]]
# A tibble: 3 x 5
    cyl   Vol   Bal `Vol %` `Bal %`
  <dbl> <int> <dbl>   <dbl>   <dbl>
1     4    11  293.   0.344   0.456
2     6     7  138.   0.219   0.215
3     8    14  211.   0.438   0.329

[[2]]
# A tibble: 27 x 5
    disp   Vol   Bal `Vol %` `Bal %`
   <dbl> <int> <dbl>   <dbl>   <dbl>
 1  71.1     1  33.9  0.0312  0.0527
 2  75.7     1  30.4  0.0312  0.0473
 3  78.7     1  32.4  0.0312  0.0504
 4  79       1  27.3  0.0312  0.0425
 5  95.1     1  30.4  0.0312  0.0473
 6 108       1  22.8  0.0312  0.0355
 7 120.      1  21.5  0.0312  0.0334
 8 120.      1  26    0.0312  0.0404
 9 121       1  21.4  0.0312  0.0333
10 141.      1  22.8  0.0312  0.0355
# … with 17 more rows

答案 1 :(得分:2)

Function <- function(x, y){ y <- sym(y)
return(x %>%
         group_by(!!y) %>% 
         summarise(Vol=n(),
                   Bal = sum(Bal)) %>% 
         mutate(
           'Vol %' = Vol/sum(Vol),
           'Bal %' = Bal/sum(Bal)
         )
)
}

df<-data.frame(Vol=seq(1,50,1),Bal=seq(1,100,2),Q=sample(LETTERS,50,replace = T),R=sample(letters,50,replace = T))
Cols <- c("Q", "R")
ListofDFs <- list()
for(i in 1:length(Cols)){
  ListofDFs[[i]] <- Function(df, Cols[i])
}

代码中有两种错别字:在for循环中,Col应该= Cols,在for循环中有一个大括号。

答案 2 :(得分:0)

不使用NSE的另一种方法是使用group_by_at,它接受​​字符串参数。

Cols <- c("Q", "W", "E","R","T","Y")
library(dplyr)

purrr::map(Cols, ~df %>%
                   group_by_at(.x) %>% 
                   summarise(Vol=n(),
                             Bal = sum(Bal)) %>% 
                   mutate('Vol %' = Vol/sum(Vol),
                          'Bal %' = Bal/sum(Bal)))