我希望将用户输入变量传递给group_by()和summarize()函数。
数据帧和代码的直接示例如下所示。这里我对列名进行了“硬编码”。
library(dplyr)
df <- data.frame('Category' = c('a','c','a','a','b','a','b','b'),
'Amt' = c(100,300,200,400,500,1000,350,250),
'Flag' = c(0,1,1,1,0,1,1,0))
rowCount <- nrow(df)
totalAmt <- sum(df$Amt)
g <- group_by(df, Category)
summ <- summarize(g, Count = n(), CountPercentage = n()*100/rowCount, TotalAmt = sum(Amt), AmtPercentage = sum(Amt)*100/totalAmt, FlagSum = sum(Flag))
summ输出如下所示

在我正在开发的应用程序中,数据帧和列名将是用户定义的。我将读取.csv文件中的文件名、要分组的列和要汇总的列。
我进行了广泛的搜索,在花费了大量的时间阅读和实验之后,我找到了下面所示的解决方案,它对我来说是有效的。我没有使用管道来使步骤更清晰。
#The data frame df is read from the .csv file name
#Variables read from the Excel file
groupby <- 'Category'
sumBy1 <- 'Amt'
sumBy2 <- 'Flag'
rowCount <- nrow(df)
totalAmt <- sum(df[sumBy1])
g <- group_by_(df, groupby) #group by variable #grouping
summcount <- summarize(g, Count = n(), CountPercentage = n()*100/rowCount) #summarize counts #piece 1
summamt <- summarize_at(g, .vars = sumBy1, .funs=sum) #summarize by first variable
summamt <- summamt[-1] #remove first column to remove duplicate column
summamt$AmtPercentage <- summamt[sumBy1]*100/totalAmt #piece 2
summflag <- summarize_at(g, .vars = sumBy2, .funs=sum) #summarize by second variable
summflag <- summflag[-1] #remove first column to remove duplicate column #piece 3
summ <- cbind(summcount, summamt, summflag) #combine dataframes
summ结果和上面的一样。正如您所看到的,我正在逐个创建最终的数据帧,然后绑定它们。代码很难看。另外,如何在此语法中定义列标题?我确实考虑过summarize_all(),但这需要创建数据帧的子集。我已经阅读了以下问题,它们对我不起作用
Passing arguments to dplyr summarize function
Summarizing data in table by group for each variable in r
你能推荐一种更简单、更优雅的方法吗?
上面我已经“硬编码”了两种类型的摘要,即。计数和求和。为了增加另一个级别的复杂性,如果用户还想定义摘要的类型(即,和、均值、计数等)必需的?在Excel文件中,我可以捕获针对每个变量所需的汇总类型。
谢谢你的建议。
发布于 2018-03-20 04:30:09
这听起来像是超人的工作!或者至少是准引语。
您希望使用!!操作符插入变量。
你可以这样做
# Make a variable symbol from strings
make_var <- function(prefix, var, suffix)
as.symbol(paste0(prefix, var, suffix))
calc_summary <- function(df, groupby, sumBy1, sumBy2) {
totalSumBy1 <- make_var("Total", sumBy1, "")
sumBy1Percentage <- make_var("", sumBy1, "Percentage")
sumBy1 <- make_var("", sumBy1, "")
sumBy2Sum <- make_var("", sumBy2, "Sum")
sumBy2 <- make_var("", sumBy2, "")
group_by_(df, groupby) %>%
summarize(Count = n(),
CountPercentage = n()*100/rowCount,
!!totalSumBy1 := sum(!!sumBy1),
!!sumBy2Sum := sum(!!sumBy2)) %>%
mutate(CountPercentage = Count/sum(Count),
!!sumBy1Percentage := 100 * !!totalSumBy1 / sum(!!totalSumBy1))
}当您使用!!时,您插入的是一个变量的值,所以这就是您可以参数化给定给dplyr函数的表达式的方式。您需要它们作为符号,这就是我使用make_var函数的原因。它可以更优雅地完成,但这将给出您在示例中使用的变量。
注意,当我们赋值的变量是动态的时,我们必须使用:=赋值而不是=赋值。否则,解析器会报错。
您可以按如下方式使用此函数:
> df %>% calc_summary("Category", "Amt", "Flag")
# A tibble: 3 x 6
Category Count CountPercentage TotalAmt FlagSum AmtPercentage
<fct> <int> <dbl> <dbl> <dbl> <dbl>
1 a 4 0.500 1700. 3. 54.8
2 b 3 0.375 1100. 1. 35.5
3 c 1 0.125 300. 1. 9.68列的顺序与示例中的不同,但您可以使用select解决这个问题。我通过在总结之后将百分比计算移动到mutate中,对百分比计算进行了一些清理。它不再需要rowCount变量。如果您愿意,可以很容易地使用该变量并避免mutate调用。然后,您还可以在summarise调用中按您想要的顺序获取列。
无论如何,重要的一点是,您需要在这里使用bang-bang运算符。
https://stackoverflow.com/questions/49371260
复制相似问题