我有以下数据(一些组织,kpi度量,一长串变量(在示例中我给出了两个)。
df <- tibble::tribble(
~ORG_NM, ~KPI_NM, ~NUMR_VAL, ~DENO_VAL,
"AAA", "xxx", 8, 10,
"AAA", "xxx", 10, 10,
"BBB", "xxx", 1, 7,
"CCC", "xxx", 9, 3,
"CCC", "yyy", 9, 4,
"DDD", "xxx", 1, 7,
"AAA", "yyy", 8, 3,
"BBB", "yyy", 6, 1
)
我想总结每个变量并生成一个宽表,以便每个组织只有一个记录。到目前为止,我的方法是使用需要更改的重复代码, -用要汇总的变量的名称汇总部分以及应使用该变量处理的函数, -展开部分-值=更改新列的名称, -named_at-将有意义的后缀添加到所有带有值的扩展列中,显示用于实现它们的函数。 最后,我需要在full_join中更改数据框的名称以追加新列。
library(tidyverse)
df_numrtr <- df %>%
group_by(ORG_NM, KPI_NM) %>%
summarise(mean_NUM_VAL = mean(NUMR_VAL)) %>%
spread(key = c(KPI_NM), mean_NUM_VAL) %>%
ungroup() %>%
rename_at(vars(-ORG_NM), function(x) paste0(x, "_num_mean"))
df_denom <- df %>%
group_by(ORG_NM, KPI_NM) %>%
summarise(mean_DENOM_VAL = mean(DENO_VAL)) %>%
spread(key = c(KPI_NM), mean_DENOM_VAL) %>%
ungroup() %>%
rename_at(vars(-ORG_NM), function(x)
paste0(x, "_den_mean"))
df_final <-
df_numrtr %>%
full_join(df_denom) %>%
select(ORG_NM, sort(names(.)))
ORG_NM xxx_den_mean xxx_num_mean yyy_den_mean yyy_num_mean
<chr> <dbl> <dbl> <dbl> <dbl>
1 AAA 10 9 3 8
2 BBB 7 1 1 6
3 CCC 3 9 4 9
4 DDD 7 1 NA NA
我想摆脱重复的代码,并拥有一个将使用变量名和函数名的函数。我想要的伪代码函数看起来像
fnSummarize <- function(df, my_org_var, my_kpi_var, my_var, my_fun ){
df_output<-df %>%
group_by({{my_groupby_var}}) %>%
summarise(paste0({{my_var}},"_",{{my_fun}}) = my_fun({{my_var}})) %>%
spread(key = {{my_kpi_var}}, paste0(my_var, my_fun)) %>%
ungroup() %>%
rename_at(vars(-{{ my_org_var}}), function(x) paste0(x, {{myfun}}))
return(df_output)
}
如何正确地将列名和过程中要使用的函数(例如均值,总和,中位数,标准差)注入到该函数中。
答案 0 :(得分:1)
您非常亲密。问题是列名的组成,我将其拖到另一行中:
fnSummarize <- function(df, my_org_var, my_kpi_var, my_var, my_fun ){
colName <- str_c( rlang::enexpr(my_var),"_",rlang::enexpr(my_fun) )
df %>%
group_by( {{my_org_var}}, {{my_kpi_var}} ) %>%
summarise( !!colName := {{my_fun}}({{my_var}}) ) %>%
spread( key = {{my_kpi_var}}, colName ) %>%
ungroup() %>%
rename_at( vars(-{{my_org_var}}), str_c, "_", colName )
}
列名与您的df_numrtr
和df_denom
略有不同,但是可以通过其他字符串操作轻松地进行调整。我将其保留以保持环境清洁。
fnSummarize( df, ORG_NM, KPI_NM, NUMR_VAL, mean )
# # A tibble: 4 x 3
# ORG_NM xxx_NUMR_VAL_mean yyy_NUMR_VAL_mean
# <chr> <dbl> <dbl>
# 1 AAA 9 8
# 2 BBB 1 6
# 3 CCC 9 9
# 4 DDD 1 NA
## Demonstrating using sum instead of mean
fnSummarize( df, ORG_NM, KPI_NM, DENO_VAL, sum )
# # A tibble: 4 x 3
# ORG_NM xxx_DENO_VAL_sum yyy_DENO_VAL_sum
# <chr> <dbl> <dbl>
# 1 AAA 20 3
# 2 BBB 7 1
# 3 CCC 3 4
# 4 DDD 7 NA
我还想指出,您可以通过纯dplyr
操作来解决任务,而无需rlang
。例如,以下是您同时应用sum
和mean
的方法:
df %>% group_by( ORG_NM, KPI_NM ) %>%
summarize_at( c("NUMR_VAL", "DENO_VAL"), list(mean=mean,sum=sum) ) %>%
ungroup() %>% gather( "Variable", "Value", -ORG_NM, -KPI_NM ) %>%
mutate( Variable = map2_chr(Variable, KPI_NM, ~str_replace(.x,"VAL",.y)) ) %>%
select( -KPI_NM ) %>% spread( Variable, Value )
# # A tibble: 4 x 9
# ORG_NM DENO_xxx_mean DENO_xxx_sum DENO_yyy_mean DENO_yyy_sum NUMR_xxx_mean
# <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 AAA 10 20 3 3 9
# 2 BBB 7 7 1 1 1
# 3 CCC 3 3 4 4 9
# 4 DDD 7 7 NA NA 1
# # … with 3 more variables: NUMR_xxx_sum <dbl>, NUMR_yyy_mean <dbl>,
# # NUMR_yyy_sum <dbl>